Как я могу написать контроллер RESTful, для которого требуется один из N родительских ресурсов? - PullRequest
1 голос
/ 22 августа 2011

Мы используем CanCan.В нашем приложении библиотеки можно извлечь Book или Magazine:

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

Books и Magazines имеют родительский класс 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  

Какой правильный способ написать LoansController с помощью CanCan, чтобы он мог обрабатывать все, что Loanableбез необходимости составлять конкретный маршрут для всего, что Loanable?

1 Ответ

0 голосов
/ 22 августа 2011

Я бы просто использовал ability.rb, чтобы определить, какие действия разрешены / запрещены для каждого типа объекта. Далее предполагается, что вы используете STI, и поэтому существует столбец stockable_type, содержащий имя класса, который каждая строка представляет в вашей базе данных. Если вы не используете STI, вы все равно можете использовать другой метод для правильного определения типа объекта (возможно, передавая блок методам can и cannot вместо использования синтаксиса хэша [проверьте вики CanCan, Определение Способности для дополнительной информации]).

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

Тогда просто поймайте CanCan::AccessDenied в своем LoansController, и вы сможете перенаправить людей, пытающихся оформить справочные книги.

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