I\'m trying to generalize some of my models by providing a common base model to inherit from that contains some mutual named_scope declarations and a filter method that activate
That's a bit of a train-wreck because of the way ActiveRecord is trying to interpret what you're saying. Generally the first class derived from ActiveRecord::Base is used to define what the base table name is, and sub-classes of that are defined to use Single Table Inheritance (STI) by default. You're working around this by using set_table_name
but, as is often the case, while it's possible to go against the grain in Rails, things often get messy.
You should be able to do this a lot more cleanly using a mixin as suggested by Beerlington.
module ByNameExtension
def self.extended(base)
# This method is called when a class extends with this module
base.send(:scope, :by_name, lambda { |name|
name.blank? ? nil : where("#{self.table_name}.name LIKE ?", "%#{name}%")
})
end
def filter(params)
params[:name].present? ? self.by_name(params[:name]) : [ ]
end
end
class MyModel < ActiveRecord::Base
# Load in class-level methods from module ByNameExtension
extend ByNameExtension
end
You should be able to keep your extensions contained to that module. If you want to clean this up even further, write an initializer that defines a method like scoped_by_name
for ActiveRecord::Base that triggers this behavior:
class ActiveRecord::Base
def scoped_by_name
extend ByNameExtension
end
end
Then you can tag all classes that require this:
class MyModel < ActiveRecord::Base
scoped_by_name
end