5

I have the models Category and Products. If I use category.products << new_product the item gets added to the array and the record is saved to the database. I tried adding the following "add" method to the array class and while it does adds the new_product to the array, it does not save it to the database. Why is that?

class Array
  def add(item)
    self << item
  end
end

Update:

collection_proxy.rb has the following method:

def <<(*records)
  proxy_association.concat(records) && self
end
alias_method :push, :<<

So the following extension works:

class ActiveRecord::Relation
  def add(*records)
    proxy_association.concat(records) && self
  end
end

Solution:

Add an alias to the CollectionProxy:

class ActiveRecord::Associations::CollectionProxy
  alias_method :add, :<<
end
2
  • Because Rails associations aren't arrays, they just claim they are. Commented Aug 15, 2012 at 21:37
  • What are they then? how can I add an "Add" method? Commented Aug 15, 2012 at 21:41

1 Answer 1

2

Edit: Manuel found a better solution

class ActiveRecord::Associations::CollectionProxy
  alias_method :add, :<<
end

Original solution:

This should get you started. It's not perfect.

class ActiveRecord::Relation
  def add(attrs)
    create attrs
  end
end

Rather than fire up a new rails project with your model names, I just used one I had for the following example:

1.9.3p194 :006 > Artist.create(:first_name => "Kyle", :last_name => "G", :email => "[email protected]")
 => #<Artist id: 5, first_name: "Kyle", last_name: "G", nickname: nil, email: "[email protected]", created_at: "2012-08-16 04:08:30", updated_at: "2012-08-16 04:08:30", profile_image_id: nil, active: true, bio: nil> 
1.9.3p194 :007 > Artist.first.posts.count
 => 0 
1.9.3p194 :008 > Artist.first.posts.add :title => "Foo", :body => "Bar"
 => #<Post id: 12, title: "Foo", body: "Bar", artist_id: 5, created_at: "2012-08-16 04:08:48", updated_at: "2012-08-16 04:08:48"> 
1.9.3p194 :009 > Artist.first.posts.count
 => 1 
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks. Do you know why it fails when you add the new record not as a hash but passing an object? (I'm getting "NoMethodError: undefined method `stringify_keys'")
@Manuel yes, add is calling create and it expects attributes as a hash. You could alter the method to something like create item.attributes but you may get some problems with protected attributes. Consider picking out the ones you need from the object.
Not quite :( create item.attributes creates the record in the database but does not make the relation (in your case artist_id is null).
@Manuel Remove the relation id from the hash first. item.attributes.delete(:category_id). It was set to nil and the create used that as the value. If it was missing from the hash, the relation would be setup.
We're almost there. Please see update. Do you know how to call the << method of the collection instead of copy/pasting its contents? I've tried many things to no avail.
|

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.