如何编写需要 N 个父资源之一存在的 RESTful 控制器?
我们使用康康。在我们的图书馆应用程序中,可以签出Book
或Magazine
:
POST /books/123/loans # LoansController#new :book_id => 123
POST /magazines/456/loans # LoansController#new :magazine_id => 456
Books
和Magazine
有一个父类< code>Stockable,所以上面等价于:
POST /stockables/123/loans # LoansController#new :stockable_id => 123
POST /stockables/456/loans # LoansController#new :stockable_id => 456
然而,并不是每个 Stockable
都可以借出:
# 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
的正确方法是什么,以便它可以处理任何事情可借
,而不需要为所有可借
制定特定路线?
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 # LoansController#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
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我只会使用ability.rb 来定义每种对象类型允许/不允许执行哪些操作。以下假设您使用的是 STI,因此有一个
stockable_type
列,其中包含每行在数据库中代表的类的名称。如果您不使用 STI,您仍然可以使用另一种方法来正确确定对象类型(可能通过将块传递给can
和cannot
方法,而不是使用哈希语法[查看 CanCan wiki,定义能力了解更多信息])。然后,只需在
LoansController
中捕获CanCan::AccessDenied
,您就可以重定向尝试签出参考书的人员。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 astockable_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 thecan
andcannot
methods instead of using the hash syntax [check the CanCan wiki, Defining Abilities for more info]).Then, just catch
CanCan::AccessDenied
in yourLoansController
and you can redirect people attempting to checkout reference books.