Search code examples
ruby-on-railsruby-on-rails-3deviseruby-on-rails-3.2before-filter

Before filter assign exception for entire controller


Every one of my Users has a has_many relation with Character. Now before they can use the application i need them to first select one Character as their main thus I want to keep redirecting them to members controller show method until they select the main character.

My approach works however there is a problem when someone for instance wants to logout before selecting a main character it keeps redirecting them to member_path. How do i add devise controller to exception to this rule and my entire members controller.

class ApplicationController < ActionController::Base
  protect_from_forgery

    before_filter :check_for_main
    skip_before_filter :check_for_main, :only => [:members => :show, :users => :sign_out]

    # Check if user has a main character selected
    private
    def check_for_main

        # Check signed in user
        if user_signed_in?

            # Check associated characters if any are set as main
            redirect_to member_path(current_user.id), :alert => "Please select your main character."
            unless current_user.characters.any?(&:main)

            end
        end
    end

end

Solution

  • I did not want to pollute my code by adding another controller to subclass Devise controller just for that one line: skip_before_filter. My first attempt was to add skip_before_filter to devise controller its self but you should really avoid that.

    Anyhow running rake routes shows that devise controllers are actually named devise/controller_name always with the devise/ prefix before the name. Since i was not going to extend devise controllers further only thing that made sense was to add a conditional statement to the method it self to skip requests from devise package.

    For all my other controllers i followed @Stuart M advice.

    My new code:

    class ApplicationController < ActionController::Base
        protect_from_forgery
    
        before_filter :check_for_main
    
        # Check if user has a main character selected
        private
        def check_for_main
    
            # Check signed in user
            if user_signed_in?
    
                if not params[:controller].to_s.include? "devise"
                    # Check associated characters if any are set as main
                    if not current_user.characters.any?(&:main)
                        redirect_to member_path(current_user.id), :alert => "Please select your main character."
                    end
                end
            end
        end
    
    end