2

I have a Rails model named Container with a column named products. It is a string array as supported by Postgres and the 'postgres_ext' gem.

The relevant portion of the GEMFILE is:

gem 'rails', '3.2.9'
gem 'pg'
gem 'postgres_ext'
gem 'activerecord-postgres-hstore', git: 'git://github.com/engageis/activerecord-postgres-hstore.git'

The relevant portion of the migration is:

 t.string :products, array: true

I am writing a public method in my Container model which adds products to this array. The method looks like this:

 attr_accessible :products

 def add_to_products(product)

  if products.blank? || products.size == 0 ## product array is either uninstantiated or blank
    products = [product.id]
  else  

    unless products.include? product.id
      products << product.id
    end
  end
end

These are the results in irb/console:

pry(main)> c = Container.first
=> #<Container id: "2765cc19-98f8-4e42-a1be-538788424ec7", name:....
pry(main)> p = Product.first
=> #<Product id: "319a25ae-87fe-4769-a9de-1a8e0db9e84f", name: ....
pry(main)> c.add_to_products(product)
pry(main)> c.products
=> nil
pry(main)> c.products= [] << "319a25ae-87fe-4769-a9de-1a8e0db9e84f"
pry(main)> c.products
=> ["319a25ae-87fe-4769-a9de-1a8e0db9e84f"]

I am scratching my head to figure out what's wrong in the add_to_products method. Can someone throw some light on this weird situation? Why is the value not being set when I pass it through this method?

3
  • By "postgre", do you mean "PostgreSQL"? Commented Jan 1, 2013 at 15:58
  • 1
    isnt it evident? Dont understand the value of the comment. Edited title, none the less. Commented Jan 1, 2013 at 16:29
  • No, it's not evident. The value of the comment was for clarification. "PostgreSQL" is the name of the DBM and it's sometimes abbreviated to "Postgres" because people don't like saying the entire name. (The team acknowledges it's unwieldy.) "Postgre" could be that or something else because StackOverflow receives questions from users around the world and they don't always spell well or know the right name. Commented Jan 1, 2013 at 17:36

2 Answers 2

5

This issue is actually arising out of the use of <<. Rails does not track in place modifications of attributes (see this issue). I outline in the usage notes that you want to avoid the << operator when using arrays, as rails will not see this change, it will actually cause issues with default values.

This can also be seen by checking the products_changed? state. It will be false when you use <<.

2

This has got to do with the fact that in Ruby assignments create local variables unless you explicitly state the receiver, which is self in this case. So:

products = [product.id]

...will create a local variable named products. Whereas:

self.products = [product.id]

...is what you are really looking for.

4
  • while that makes sense, self.products did not really solve the problem. Commented Jan 2, 2013 at 14:19
  • @papdel Did you restart the server? Have you added debugging code to your add_to_products method? If not then you should, because it looks like something in there is not happening like you expect. So debug it. Just staring at the code doesn't help. Isolate the problem. logger.debug is your friend. Also you might want to read: guides.rubyonrails.org/debugging_rails_applications.html Commented Jan 2, 2013 at 16:50
  • This is due to the way attribute changes are tracked in rails. See my answer for more details Commented Feb 4, 2013 at 15:24
  • Thanks Dan, I bypassed it through a different route, but this was exactly what I was looking for. Commented Feb 4, 2013 at 19:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.