junaid edited this page Sep 14, 2010 · 36 revisions
Clone this wiki locally

This is a forked repository. Have a look at
ryanb’s cancan wiki
for more information.

Added return_disabled parameter in can?/cannot? method so that user can disable the html elments in view as sometimes we are only interested to disable html buttons/links on ui. I think its good if we could put all logic related to disable and visible in ability file otherwise we have to write same code both in views and controller for disabling and restricting access.

For example
There are four html buttons that perform different actions by sending ajax request. We have two roles ‘admin’ and ‘guest’ . Only ‘admin’ role users can access following buttons but in sequence just like some business workflow in which we can’t go on next step until we complete previous one. So initially we would like to hide all button for users who have ‘guest’ role, enable(clickable) button1 and disable button 2,3 & 4 for ‘admin’ role because ‘admin’ role user can click button 2 once he has clicked the button 1 and so on. To achieve this behavior we do in view as follows

def button_helper(button_name, show_or_disabled)
button_to button_name, :class=>"button #{show_or_disabled} if show_or_diabled
end <%= button_helper(“button_1”, can(:click_button1, cron_workflow, :return_disabled=>true)) %> <%= button_helper(“button_2”, can (:click_button2, cron_workflow, :return_disabled=>true)) %> <%= button_helper(“button_3”, can(:click_button3, cron_workflow, :return_disabled=>true)) %> <%= button_helper(“button_4”, can(:click_button4, cron_workflow, :return_disabled=>true)) %>

we will have ability like this

if user.admin?
can :click_button1, cron_workflow do |workflow|
(!workflow.button1_is_clicked?) ? true : “disabled”
can :click_button2, cron_workflow do |workflow|
(workflow.button1_is_clicked? && !workflow.button2_is_clicked?) ? true : “disabled”
can :click_button3, cron_workflow do |workflow|
(workflow.button1_is_clicked? && workflow.button2_is_clicked? && !workflow.button3_is_clicked?) ? true : “disabled”
can :click_button4, cron_workflow do |workflow|
(workflow.button1_is_clicked? && !workflow.button2_is_clicked? && workflow.button3_is_clicked? && !workflow.button4_is_clicked?) ? true : “disabled”

How to access parent resource in ability block?
Assume we have url like http://www.example.com/tenders/1/assignments in which tender is parent object. We have assignment controller
like this

class AssignmentsController < ApplicationController
load_and_authorize_resource :nested => :tender
def index
def show

then we can access parent object in collection action like this

can :index, Assignment do |params|
params = params.last

Access parent object if action is not collection-actions

can :show, Assignment do |params|
assignment = params.first
params = params.last
tender = params[:tender]
tender.is_public? && assignment

How to give custom message and redirect url in ability definition?
can :action, :controller, condition, redirect_url, custom_message

can :read, :foo, nil, “\login”, “You have to login to access this page”