I am trying to dynamically add a scope to an active record object. Some of the things I have been trying via metaprogramming are not working. Below is sort of what I want to achieve.
class UtilityClass
def add_scope_to_class klass, name, lambda
# should add something like
# scope :published, -> { where(published: true) }
code = lambda { filter_clause(value, &lambda) }
klass.class_exec(&code)
end
end
class Article < ActiveRecord::Base
end
UtilityClass.add_scope_to_class
Article.published # returns published articles
I have tried a couple of variations of this with plain ruby objects, but I thought asking the question with this context might get some different ideas/answers.
Thanks.
Updated
So far I have managed to come up with the following but it's not working
class ActiveSearch
attr_accessor :collection
attr_reader :params
def initialize params={}
@params = params
end
def results
@collection = Person.where(nil)
params.compact.each do |key, value|
@collection = @collection.send("#{key}_filter", value)
end
@collection
end
def self.filter name, filter_proc
code = lambda { |filter_name| scope("#{filter_name.to_s}_filter".to_s, filter_proc) }
Person.class_exec(name, &code)
end
end
class PersonSearch < ActiveSearch
filter :first_name, ->(name){ where(first_name: name) }
end
I have hard coded a couple of things. The main idea is there.
After playing around, I found the solution is a bit simpler than I originally thought.
The above will combine all the appropriate methods and execute the query.
A couple of tweaks are needed, but it's pretty much doing what I want. The active search class still needs to be cleaned up and made generic, but I think it gets the idea across.