Qaz
Qaz

Reputation: 1576

Rails foo= vs foo_id=

If bar belongs_to foo and foo has_many bars, is there a difference between the effects of

my_bar.foo = my_foo

and

my_bar.foo_id = my_foo.id

or do both make an association between my_foo and my_bar?

I ask because I'm trying to decide whether to add the association manually when I override the setter for Bar#foo_id=(input).

Upvotes: 3

Views: 148

Answers (2)

AJFaraday
AJFaraday

Reputation: 2450

The main difference is that bar_id can not be filled in until the Bar record has been saved (when the id attribute is assigned). You can build a Bar object in memory and associate it with a bar (the foo = part) before saving either record. Usually, when you save the Bar, the foo will also be validated and saved.

  • foo_id is the attribute which will be saved to the database, which will refere to a record in the FOOS table.
  • foo is an instantiated ActiveRecord object which is stored as an attribute against of the bar object.

As a rule, if you are associating a new Bar with an existing foo, I would set the foo_id. If you are creating them at the same time, I would set the foo.

Edit: Having seen the last part of your question. If you override the setter to add functionality, I would start by calling super(value) to get all the existing functionality from ActiveRecord. E.g.

def foo_id=(value)
  super(value)
  @foo_id = value
  do_other_thing
end

I would recommend overriding this method in a way which removes this functionality.

Upvotes: 1

Max Williams
Max Williams

Reputation: 32933

Your question contains a slight inaccuracy, in that neither of these create an association: they set the association up ("build" it, if you like), but it won't be created, ie saved into the database, until my_bar is saved.

Both of these should set the proxy for each other: if you say my_bar.foo_id = 4, then my_bar.foo should return the foo with id 4, even before it's saved, and vice versa.

If you are going to override the setter for Bar#foo_id (by convention, when describing methods, the hash denotes an instance method rather than a class method), you could get yourself into trouble if you don't replicate the natural behaviour of Rails. Tread carefully.

Upvotes: 1

Related Questions