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.

188 CHAPTER 8 More authorization<br />

To make the spec pass, you need to implement the permission checking on the new<br />

and create actions in your TicketsController.<br />

Run a before_filter before the new action that checks whether the current user<br />

has permission; if not, then redirect the user to the project page and display the error<br />

described in the spec.<br />

Now change the before_filter calls to include this new one, as shown in the following<br />

lines:<br />

before_filter :authenticate_user!<br />

before_filter :find_project<br />

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

before_filter :authorize_create!, :only => [:new, :create]<br />

This authorize_create!before_filter is placed after the authenticate_user! and<br />

find_project before_filters because it uses the current_user object set up by the<br />

authenticate_user! method and the @project object from find_project.<br />

In this new filter, you call a new method called cannot?, which returns true or<br />

false to indicate whether the currently signed-in user can’t or can do a particular<br />

action. You define the authorize_create! method code shown next:<br />

def authorize_create!<br />

if !current_user.admin? && cannot?("create tickets".to_sym, @project)<br />

flash[:alert] = "You cannot create tickets on this project."<br />

redirect_to @project<br />

end<br />

end<br />

In this example, you use to_sym to create a symbolized version of a string, which is<br />

required because the cannot? method takes only symbols. You also check whether or<br />

not the user is an admin; if so, the user should be allowed to create tickets. If you run<br />

the controller’s spec again with bin/rspec spec/controllers/tickets_controller<br />

_spec.rb, the example fails because the cannot? method is undefined:<br />

Failure/Error: get :new, :project_id => project.id<br />

undefined method 'cannot?' for #<br />

Rails doesn’t come with a cannot? method, but a gem called cancan (stylized as Can-<br />

Can) does. This gem helps you tie together the User and Permission records. Let’s<br />

install it now.<br />

8.5.3 What is CanCan?<br />

CanCan is a gem written by Ryan Bates of Railscasts fame; it provides some nice helper<br />

methods (such as the cannot? method and its antithesis, can?) to use in controllers<br />

and views.<br />

The can? and cannot? methods use the same permissions table you created to<br />

check that a user has permission to perform a specific action on a specific object.<br />

To install CanCan, add this line to your Gemfile directly underneath the line for<br />

Devise:<br />

gem 'cancan'

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

Saved successfully!

Ooh no, something went wrong!