Search code examples
ruby-on-railsscopes

Rails - add scope for certain controllers in a module based up a database setting


I have an api. In that api is a basecontroller that all other controllers inherit from. The basecontroller handles authentication and whether or not the API is on at all, etc.

There are users, and users can belong to a group. Users table has a group_id column.

I'm trying to introduce a new feature, whereby a select on the settings page for admin controls which users are shown from what groups. If an option is selected, only users from that group should be shown by the api.

I could go into each controller (there is one controller for each of a few different tasks - getting all users info, just active_users ids, a single users information, etc) and add the extra statement to each

if !settings.api_group.nil?
  #add the additional where("group_id = ?, settings.group_id)

but that seems like a lot of repeating myself (doing it in 8 different places)

Is there some way to add something to the basecontroller that says:

if this setting option is not nil, only return user information if they are in this group

?

Thanks


Solution

  • You can add a method to the BaseController, and call it in each action that should have this restriction. Something like this:

    in base_controller.rb:

    protected
    
    def filtered_users
      if settings.api_group
        User.where(:group_id => settings.group_id)
      else
        User.scoped
      end
    end
    

    and in the controllers that inherit from it:

    def index
      @users = filtered_users
    end
    

    This way, you only define the filtering in one place. If it needs to change later, you only have to change it in one place. Because filtered_users actually returns a Relation, you can continue to alter the query by tacking additional .where clauses, etc, like this:

    @users = filtered_users.joins(:posts).where('posts.created_at > ?', 1.week.ago)