在我的标题中,我有一个材料页面的链接,我不想让任何人访问,所以我需要在视图中设置条件和在MaterialsController中使用before_filter。
我为视图编写了一个成功的帮助方法,但本着DRY的精神,我想在ApplicationController中只编写一次该方法,并使用helper_method将其提供给视图:
的ApplicationController:
helper_method :user_is_admin_or_teacher_or_student_with_a_class
def user_is_admin_or_teacher_or_student_with_a_class
if user_signed_in? and ( current_user.admin || current_user.type == "Teacher" || ( (current_user.type == "Student") and current_user.groups.any? ) )
else redirect_to root_path, alert: "You are not authorised to view the Materials page."
end
end
这在我的MaterialsController中完美运行:
before_action :user_is_admin_or_teacher_or_student_with_a_class, only: [:index, :show]
它具有预期的效果。
转到帮助方面,我把它放在我的视图中(_header.html.erb):
<% if user_is_admin_or_teacher_or_student_with_a_class %>
<li><%= link_to "Materials", materials_path %></li>
<% end %>
但是当我尝试在浏览器中加载我的主页时,我得到'此页面有一个重定向循环'浏览器错误。我假设这与控制器方法中的redirect_to root_path命令有关。
我的原始解决方案是从ApplicationController中删除helper_method声明,并在ApplicationHelper中编写一个几乎相同的方法:
def user_is_admin_or_teacher_or_student_with_a_class?
user_signed_in? and ( current_user.admin || current_user.type == "Teacher" || ( (current_user.type == "Student") and current_user.groups.any? ) )
end
这项工作,但它不是干的。如何干这个并只编写一次方法并在控制器和视图中使用它?
答案 0 :(得分:2)
我分裂了逻辑。您可以将此方法放在模型中(我假设它是用户):
class User < ActiveRecord::Base
# ...
def can_view_materials?
# note no need for parentheses here if '&&' is used instead of 'and' operator
admin || type == "Teacher" || type == "Student" && groups.any?
end
# ...
end
然后在MaterialsController
:
before_action :require_authorization_to_view_materials, only: [:index, :show]
def require_authorization_to_view_materials
unless user_signed_in? && current_user.can_view_materials?
redirect_to root_path, alert: "You are not authorised to view the Materials page."
end
end
最后,在您看来:
<% if user_signed_in? && current_user.can_view_materials? %>
<li><%= link_to "Materials", materials_path %></li>
<% end %>
这只是你的方法的精致版本。可以通过其他一些更好的方式实现,引入额外的授权逻辑,用户角色等等。但这一切都取决于您的解决方案将会变得多么复杂,以及您是否真的需要它。
注意没有辅助方法来自控制器方法;)
如果您真的想要创建一个控制器/视图常用方法来检查用户权限,可以在ApplicationController
中执行此操作:
helper_method :user_can_view_materials?
def user_can_view_materials?
user_signed_in? && current_user.can_view_materials?
end
和MaterialsController
:
def require_authorization_to_view_materials
redirect_to root_path, alert: "You are not authorised to view the Materials page." unless user_can_view_materials?
end
并在视野中:
<% if user_can_view_materials? %>
<li><%= link_to "Materials", materials_path %></li>
<% end %>
答案 1 :(得分:0)
你的root_path指向你正在重定向的同一个控制器。更改重定向路径或根路径
# routes.rb
Rails.application.routes.draw do
root change_whatevers_here
end
或
redirect_to change_whatevers_here, alert: "You are not authorised to view the Materials page."