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.

Restricting by scope<br />

response.should redirect_to(projects_path)<br />

flash[:alert].should eql("The project you were looking for could not be fou<br />

nd.")<br />

end<br />

You use the same error message from the missing project spec because you don’t<br />

want to acknowledge to unauthorized users that the project they’re looking for exists<br />

when they don’t have access to read it. When you run this spec using bin/rspec spec<br />

/controllers/projects_controller_spec.rb, it fails:<br />

1) ProjectsController standard users cannot access the show action<br />

Failure/Error: response.should redirect_to(projects_path)<br />

The spec fails because you haven’t yet scoped down the find call in the find_project<br />

method, which is called using a before_filter in ProjectsController.<br />

With a failing spec testing the nonexistent behavior, open app/controllers/<br />

projects_controller.rb and change the find_project method to look for projects that<br />

the current user has access to so your spec will pass. But there’s one problem: you’re<br />

not restricting the show action to only users who are signed in now.<br />

You must make it so that the user has to sign in before accessing the show action<br />

because you need to use the current_user method to check what permissions this<br />

user has access to within the find_project method.<br />

To do so, call the authenticate_user! method as a before_filter in this controller,<br />

just as you did for certain actions in the TicketsController. Place this<br />

method above the find_project to ensure that a user is authenticated before<br />

find_project does its job. The filters in ProjectsController should now look like<br />

the following listing.<br />

Listing 8.4 app/controllers/projects_controller.rb<br />

before_filter :authorize_admin!, :except => [:index, :show]<br />

before_filter :authenticate_user!, :only => [:show]<br />

before_filter :find_project, :only => [:show, :edit, :update, :destroy]<br />

Now alter the find_project method to check the permissions of the project before<br />

letting authorized users see it or refusing unauthorized users access. Change the line<br />

that defines the @project variable from this<br />

@project = Project.find(params[:id])<br />

to this:<br />

@project = Project.readable_by(current_user).find(params[:id])<br />

The readable_by method doesn’t exist yet; you’ll define it in just a moment. The<br />

readable_by method returns a scope of only the projects the user is allowed to view.<br />

This scope has exactly the same methods that an Active Record class has, so you can<br />

treat it just like one. You can define this method using the scope class method in your<br />

Project mode.<br />

169

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

Saved successfully!

Ooh no, something went wrong!