27.02.2013 Views

Rails%203%20In%20Action

Rails%203%20In%20Action

Rails%203%20In%20Action

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Attaching many files<br />

<br />

<br />

<br />

<br />

Directly before the fields_for call, you set a local variable called number, which is<br />

incremented whenever you render a label B.<br />

You use fields_for much in the same way you use form_for. You call fields_for<br />

on the f block variable from form_for, which tells it you want to define nested fields<br />

inside this original form. The argument to fields_for—:assets C—tells Rails the<br />

name of the nested fields.<br />

The file field inside this fields_for now has the name attribute of<br />

ticket[assets][asset] rather than simply ticket[asset], meaning it will be available<br />

in the controller as params[:ticket][:assets][:asset].<br />

When you run this scenario with bin/cucumber features creating_tickets<br />

.feature:36, it now fails because it still can’t find the second file-upload field:<br />

And I attach the file "spec/fixtures/spin.txt" to "File #2"<br />

cannot attach file, no file field with id, name,<br />

or label 'File #2' found (Capybara::ElementNotFound)<br />

To make this appear, you must define an assets association in your Ticket model so<br />

the fields_for in your view will provide file_fields for three new Asset objects. If<br />

this method is available and you’ve declared that your model accepts nested attributes<br />

for this association, fields_for iterates through the output from this method and<br />

renders the fields from fields_for for each element.<br />

You can define this assets method by defining a has_many association in your<br />

Ticket model:<br />

has_many :assets<br />

Underneath this has_many, you also define that a Ticket model accepts nested attributes<br />

for assets by using accepts_nested_attributes_for:<br />

accepts_nested_attributes_for :assets<br />

This little helper tells your model to accept asset attributes along with ticket attributes<br />

whenever you call methods like new, build, and update. It has the added bonus of<br />

switching how fields_for performs in your form, making it reference the association<br />

and calling the attributes it defines assets_attributes rather than assets.<br />

When you run the scenario with bin/cucumber features/creating_tickets<br />

.feature:38, you see again that the Asset is not defined:<br />

And I follow "New Ticket"<br />

uninitialized constant Ticket::Asset (ActionView::Template::Error)<br />

You’d best get onto that then!<br />

C The assets<br />

223

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!