2

I have many scopes that use date ranges to do something, e.g. clicks_between(start_date, end_date). I also have want to support adding in a school year string, where we have an existing SchoolYear that has a start and end methods.

I could do something like:

scope :clicks_during, -> (year) {
    year = Year.new(year) if year.is_a?(Integer)
    send('clicks_between', year.start, year.end) 
}

However, I'd rather not have to copy and paste this code everywhere. Is there a way to just dynamically add this scope if the "betweeen" scope exists already?

Huey
  • 2,714
  • 6
  • 28
  • 34
  • I think you're looking for concerns. https://stackoverflow.com/questions/14541823/how-to-use-concerns-in-rails-4 – Josh Brody Dec 05 '17 at 07:13

1 Answers1

2

Applying the concept of concerns, you may group together dependent scopes inside a module and include that module in the models as you need. Moreover as your scopes do accept arguments, using a class method is the preferred way in place of scopes. For more, please check Passing in arguments.

module Clickable
  extend ActiveSupport::Concern

  class_methods do
    def clicks_between(start_date, end_date)
      # ...
    end

    def clicks_during(year)
      year = Year.new(year) if year.is_a?(Integer)
      send('clicks_between', year.start, year.end)
    end
  end
end

In your model:

class SomeModel < ActiveRecord::Base
  include Clickable
end

class OtherModel < ActiveRecord::Base
  has_many :some_models
end

Now you can call scopes as usual:

SomeModel.clicks_during(2017)
other_model.some_models.clicks_during(2017)

ActiveSupport::Concern api

Wasif Hossain
  • 3,900
  • 1
  • 18
  • 20