In my header, I have a link to a Materials page that I don't want just anyone to access, so I need a condition set in my view and a before_filter in my MaterialsController.
I wrote a successful helper method for the view, but in the spirit of DRY, I wanted to write that method just once in the ApplicationController and make it available to the view using 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
This worked perfectly in my MaterialsController:
before_action :user_is_admin_or_teacher_or_student_with_a_class, only: [:index, :show]
It has the desired effect.
Moving onto the helper side of things, I placed this in my view (_header.html.erb):
<% if user_is_admin_or_teacher_or_student_with_a_class %>
<li><%= link_to "Materials", materials_path %></li>
<% end %>
But when trying to load my homepage in the browser, I get the 'this page has a redirect loop' browser error. I assume this is to do with the redirect_to root_path command in the controller method.
My crude solution was to remove the helper_method declaration from ApplicationController and write an almost identical method in 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
Of this works, but it's not DRY. How can I DRY this up and write the method just once and use it in Controllers and in Views?