Monday, March 24, 2008

params[:fu] #2 ) Put attributes into a different params key using fields_for if they belong to different models.

fields_for is very useful for separating out your params:

<% form_for @reader do |f| %>
<%= f.text_field :name %
>

<% fields_for :favourite_computer, @computer do |ff| %>
<%= ff.text_field :name %
>
<% end %>
<%= f.submit 'Create' %
>
<% end %>


Processing ReadersController#create (for 127.0.0.1 at 2008-01-14 21:12:56) [POST]
Parameters: { "commit" => "Create",
"reader" => { "name" => "stephen chu" },
"favourite_computer" => { "name" => "macbook pro" },
"authenticity_token" => "238ba79b8282882ba01d840352616c2cc79280f0",
"action" => "create",
"controller" => "readers" }


def create
@reader = Reader.new params[:reader]
@computer = @reader.build_computer params[:favourite_computer]
if @reader.save
flash[:success] = 'Good.'
else
flash[:error] = 'Bad.'
end
end

class Reader < ActiveRecord::Base
has_one :computer
validates_associated :computer
end


Here, I am on a page that creates the reader and its favorite computer. Two models sounds hard? Not really, if you key your params to a different key for each of the model, your controller is still nice and thin. You do need to add one line to the action to create the computer though, but that maps nicely to the fact that you are operating on two models from the page post. I would not want to add more than one line of code to create one additional model, so forget those params-munging/looping.

Also, you can see that I am using validates_associated here. The point being I do not want to call save or valid? once for each model in my action, making my controller code fat.

Also, fields_for is not only just a helper method, but also a method available on your FormBuilder as well (you know, the f in your form_for is an instance of a FormBuilder. To see an example of how to call it off of a form builder, check out this blog entry.

(back to the TOC of the params[:fu] series)

1 comment:

Morto said...

Well I would actually do the build_computer at the reader model,using virtual attributes and my associated model would still get validated :)