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.

226 CHAPTER 9 File uploading<br />

you haven’t yet defined the has_attached_file in the Asset model, right? Yup, you<br />

should do that!<br />

Open app/models/asset.rb, and add this line:<br />

has_attached_file :asset<br />

Remove the same line from app/models/ticket.rb because you no longer need it. Having<br />

this has_attached_file defined in the Asset model is probably all you need.<br />

You’ve had all three file fields displaying, and now you’ve got your Asset model set up<br />

to receive these files. When you run the scenario again using bin/cucumber features<br />

/creating_tickets.feature:38, it all passes:<br />

1 scenario (1 passed)<br />

18 steps (18 passed)<br />

Hooray, the scenario passed! In this section, you set up the form that creates new<br />

Ticket objects to also create three associated Asset objects by using nested attributes.<br />

This process was made possible by moving the responsibility of handling file uploads<br />

out of the Ticket model and into the associated Asset model.<br />

Let’s ensure that nothing is broken by running rake cucumber:ok spec:<br />

46 scenarios (46 passed)<br />

470 steps (470 passed)<br />

# and<br />

21 examples, 0 failures, 4 pending<br />

Awesome, let’s commit and push this:<br />

git add .<br />

git commit -m "Users can now upload 3 files at a time"<br />

git push<br />

Great. You’re done with nested attributes! Earlier, it was mentioned that the files<br />

uploaded to your application are publicly available for anybody to access because<br />

these files are in the public directory. Any file in the public directory is served up automatically<br />

by any Rails server, bypassing all the authentication and authorization in<br />

your application. This is a bad thing. What if one of the projects in your application<br />

has files that should be accessed only by authorized users?<br />

9.3 Serving files through a controller<br />

You can solve this issue by serving the uploaded files through a controller for your<br />

application. Using a before_filter similar to the one you used previously in the<br />

TicketsController, this controller will check that the user attempting to access a file<br />

has permission to access that particular project.<br />

When you implemented permission behavior before, you ensured that any unauthorized<br />

user would be blocked from accessing the resource you were trying to protect<br />

by writing a controller spec. You write this same kind of spec test for serving files.

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

Saved successfully!

Ooh no, something went wrong!