heartcombo/has_scope

Allow default options on the controller level

hschne opened this issue · 2 comments

As far as I know it is not possible to set default options to be used by all scopes in a specific controller.

The use case that I have is that there are a bunch of scopes in my controller, but all of them should only apply to the index action. Currently I would have to add only: :index to each of those.

has_scope :for_project, as: 'project_id', only: :index
has_scope :for_section, as: 'section_id', only: :index
has_scope :starred, type: :boolean, as: 'focused', only: :card_index: 
...

It would be nice to be able to set a bunch of defaults to be used by has_scopes in the controller. I can imagine that this might not only be useful for only and except but possibly also with if.

A trivial solution could be something like this:

scope_default_options = { only: :index } 

has_scope :for_project, as: 'project_id'
has_scope :for_section, as: 'section_id'
has_scope :starred, type: :boolean, as: 'focused'

This can be accomplished simply enough by adding a new class field and merging these contents in has_scope, like so:

def has_scope(*scopes, &block)
   options = scopes.extract_options!
   options.symbolize_keys!
   options.assert_valid_keys(:type, :only, :except, :if, :unless, :default, :as, :using, :allow_blank, :in)

   options.merge!(self.scope_default_options)
...

However, there might be a more robust solution, not sure what troubles this 'dumb' solution might cause.

Besides: Do you consider this a valid feature request and would consider merging something like that if I create a PR?

@hschne I believe you can rely on Rails with_options Object extension for doing that, without adding new configuration to has_scope:

with_options only: :index do |opts|
  opts.has_scope :for_project, as: 'project_id'
  opts.has_scope :for_section, as: 'section_id'
  opts.has_scope :starred, type: :boolean, as: 'focused'
end

I believe this would also work, without the block arg:

with_options only: :index do
  has_scope :for_project, as: 'project_id'
  has_scope :for_section, as: 'section_id'
  has_scope :starred, type: :boolean, as: 'focused'
end

https://api.rubyonrails.org/classes/Object.html#method-i-with_options

Hopefully that's enough for what you propose / need here, let us know otherwise. Thanks!

Didn't know about with_options! This definitely works. Thanks a lot!