Rather than including the concern in each model, I'd suggest creating an ActiveRecord
submodule and extend ActiveRecord::Base
with it, and then add a method in that submodule (say include_importable
) that does the including. You can then pass the field name as an argument to that method, and in the method define an instance variable and accessor (say for example importable_field
) to save the field name for reference in your Importable
class and instance methods.
So something like this:
module Importable
extend ActiveSupport::Concern
module ActiveRecord
def include_importable(field_name)
# create a reader on the class to access the field name
class << self; attr_reader :importable_field; end
@importable_field = field_name.to_s
include Importable
# do any other setup
end
end
module ClassMethods
# reference field name as self.importable_field
end
module InstanceMethods
# reference field name as self.class.importable_field
end
end
You'll then need to extend ActiveRecord
with this module, say by putting this line in an initializer (config/initializers/active_record.rb
):
ActiveRecord::Base.extend(Importable::ActiveRecord)
(If the concern is in your config.autoload_paths
then you shouldn't need to require it here, see the comments below.)
Then in your models, you would include Importable
like this:
class MyModel
include_importable 'some_field'
end
And the imported_field
reader will return the name of the field:
MyModel.imported_field
#=> 'some_field'
In your InstanceMethods
, you can then set the value of the imported field in your instance methods by passing the name of the field to write_attribute
, and get the value using read_attribute
:
m = MyModel.new
m.write_attribute(m.class.imported_field, "some value")
m.some_field
#=> "some value"
m.read_attribute(m.class.importable_field)
#=> "some value"
Hope that helps. This is just my personal take on this, though, there are other ways to do it (and I'd be interested to hear about them too).