Ruby on rails 3 如何编写需要N个父资源之一存在的RESTful控制器?

Ruby on rails 3 如何编写需要N个父资源之一存在的RESTful控制器?,ruby-on-rails-3,rest,cancan,Ruby On Rails 3,Rest,Cancan,我们使用CanCan。在我们的图书馆应用程序中,可以签出书籍或杂志: POST /books/123/loans # LoansController#new :book_id => 123 POST /magazines/456/loans # LoansController#new :magazine_id => 456 书籍和杂志有一个父类可存储,因此上述内容相当于: POST /stockables/123/loans # LoansController

我们使用CanCan。在我们的图书馆应用程序中,可以签出
书籍
杂志

POST /books/123/loans      # LoansController#new :book_id     => 123
POST /magazines/456/loans  # LoansController#new :magazine_id => 456
书籍
杂志
有一个父类
可存储
,因此上述内容相当于:

POST /stockables/123/loans  # LoansController#new :stockable_id => 123
POST /stockables/456/loans  # LoansController#new :stockable_id => 456
但是,并非所有可储存的
都可以借出:

# 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      # LoansController#new :stockable_id      => 789  

使用CanCan编写
LoansController
的正确方法是什么,这样它就可以处理任何
可贷的
,而不需要为所有
可贷的
创建特定的路径?

我只需要使用
ability.rb
来定义每种对象类型允许/不允许的操作。下面假设您使用的是STI,因此有一个
stockable\u type
列,其中包含数据库中每行表示的类的名称。如果您不使用STI,您仍然可以使用另一种方法来正确确定对象类型(可能通过将块传递给
can
cannot
方法,而不是使用哈希语法[查看CanCan wiki,了解更多信息])

然后,只需在
LoansController
中捕获
CanCan::AccessDenied
,您就可以重定向试图结帐参考书的用户

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

我不确定我是否喜欢这个解决方案,因为它仍然公开了一个自动中断的路由(
POST/reference\u books/123/loans
),这不是非常RESTful的。如果你的routes.rb公开了
/reference\u books/:id/loans
,那么它公开的事实不是与你实际提出的问题无关吗?没有办法编写您的
LoansController
,这样它就不会暴露出一条中断的路径-它们是完全独立的子系统(我相信您已经知道)。
rescue_from CanCan::AccessDenied do |exception|
  redirect_to some_url, :alert => "You can't check out reference books!"
end