belongs_to --- has_many should update automatically?

On p. 299 of the current Rails book it says that "Active Record takes care of saving all the dependent child rows when you save a parent row." So, when I add a row to the table that has "belongs_to" in its model, shouldn't the table with the "has_many" be updated with data from the foreign key? If not, how do I save data from a form into more than one table? (And, maybe unfairly expanding into a second question, how could I put fields from multiple tables on a web page so that when it is filled out the values will go into various tables?) In both of these forms of questions I'm trying to get an answer to how data that will go into multiple tables can come from one web page. I hope my statement of the problem isn't too confusing.         Thanks,             Barney

It’s a common problem and there’s isn’t one answer.

I’ll give you three:

  1. If the objects have relationships to eachother, specify accepts_nested_attribtues_for in your models and then let active record do its thing (what you described in your post works only if you do accepts_nested_attribtues_for in your models). If class Apple has_one :orange and also accepts_nested_attributes_for :orange, you can have fields on your form like this:

text_field_tag “apple[orange][skin]”, “peeled”

  1. Hack together a single form that contains parameters from two different objects. On the controller, you’ll get params[:apple] and params[:orange]

You can’t use form_for as a resource oriented form_for, but you can use form_for and just give the fields custom names that are scoped to the objects you want to scope

text_field_tag “apple[variety]”, “golden delicious”

text_field_tag “orange[skin]”, “peeled”

In your controller, you would do something like this

@apple.update_attributes(params[:apple])

@orange.update_attributes(params[:orange])

That’s a little hacky, to be frank. If you were doing this with two distinct objects I might do a quick hack like that, but it’s not scalable.

  1. Take the example of a Registration process. Let’s say you want to register a camper for summer camp (nice July-appropriate example). One thing you can do is create a Registration object that synthesizes all the other things together. If your Registration object itself has database records, you can use something like strategy #1 above. But, keep in mind that your Registration object doesn’t have to be ActiveRecord (or have database records) at all. Experiment with (or just think about) making a Ruby model object that has no active record component.

In that paradigm, the Ruby model object (that does not inherit from active record and also does not have database records), represents the transaction. You won’t keep it around after the controller it done (because it will be gone from memory after the execute is done). But you can instantiate it, work with it, write business logic on it, pass it messages (call methods) and let it update other objects in your system.

That would be a more globalized strategy if say, you wanted to submit one form and have it touch 5 different objects.

-Jason

Thanks Jason,      The first option sounds like it would be the most consistent with Rails so I'll read up on accepts_nested_attributes_for and try to make that work.                Barney