开发者

How can I write a RESTful controller that requires one of N parent resources to exist?

We use CanCan. In our library application, a Book or Magazine can be checked out:

POST /books/123/loans      # LoansController#new :book_id     => 123
POST /magazines/456/loans  # LoansController#new :magazine_id => 456

Books and Magazines have a parent class Stockable, so the above is equivalent to:

POST /stockables/123/loans  # LoansController#new :stockable_id => 123
POST /stockables/456/loans  # LoansController#new :stockable_id => 456

However, not every Stockable can be loaned:

# error: can't check out reference books from the library
POST /reference_books/789/loans # LoansController#new :reference_book_id => 789

# same error
POST /stockables/789/loans      # LoansContr开发者_开发百科oller#new :stockable_id      => 789  

What's the right way to write the LoansController with CanCan so that it can handle anything that's Loanable, without needing to make a specific route for everything that's Loanable?


I would just use ability.rb to define what actions are / are not allowed for each object type. The following is assuming you're using STI, and so there is a stockable_type column containing the name of the class each row represents in your db. If you aren't using STI you can still use another method to correctly determine object type (probably by passing a block to the can and cannot methods instead of using the hash syntax [check the CanCan wiki, Defining Abilities for more info]).

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    can [:read], :all
    can :new, Loan, :stockable_type => ["Book", "Magazine"]
    cannot :new, Loan, :stockable_type => "ReferenceBook"
  end
end

Then, just catch CanCan::AccessDenied in your LoansController and you can redirect people attempting to checkout reference books.

rescue_from CanCan::AccessDenied do |exception|
  redirect_to some_url, :alert => "You can't check out reference books!"
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜