Подход до фильтра все еще в порядке. Вы можете получить доступ к тому, какое действие было запрошено, используя метод action_name
контроллера.
before_filter :check_authorization
...
protected
def check_authorization
@post = Post.find_by_slug(params[:slug])
if @post.user != current_user
flash[:notice] = (action_name == "destroy") ?
"You cannot delete another author’s posts." :
"You cannot edit another author’s posts."
redirect_to root_path and return false
end
end
Извините за троичного оператора посередине. :) Естественно, вы можете делать любую логику, какую захотите.
Вы также можете использовать метод, если хотите, и избежать двойного рендеринга, явно возвращая его в случае сбоя. Ключевым моментом здесь является возврат, чтобы вы не делали двойной рендер.
def destroy
@post = Post.find_by_slug(params[:slug])
return unless authorized_to('delete')
...
end
protected
def authorized_to(mess_with)
if @post.user != current_user
flash[:notice] = "You cannot #{mess_with} another author’s posts."
redirect_to root_path and return false
end
return true
end
Вы могли бы упростить это больше (на мой взгляд), разделив различные части поведения (авторизация, обработка неверной авторизации) следующим образом:
def destroy
@post = Post.find_by_slug(params[:slug])
punt("You cannot mess with another author's post") and return unless author_of(@post)
...
end
protected
def author_of(post)
post.user == current_user
end
def punt(message)
flash[:notice] = message
redirect_to root_path
end
Лично я предпочитаю переложить всю эту рутинную работу на плагин. Мой личный любимый плагин авторизации - Авторизация . Я использовал его с большим успехом в течение последних нескольких лет.
Это изменит ваш контроллер для использования вариантов:
permit "author of :post"