1

I have a child model, which should be able to store different attributes via the ActiveRecord::Store feature. Those attributes should be determined by the parent model. For this purpose, the parent model has a column content_attributes which stores the children's attributes as array of strings (i.e. ['color', 'size', 'age']).

To have accessors in the child instances for all attributes defined by the parent, i currently use a workaround which maps all attribute names of all available parents:

class child
  belongs_to :parent

  store :content, accessors: Parent.all_content_attributes, coder: JSON
  ...
end

Actually, i only want to set accessor's for all attributes of the distinct parent. However, in the example above, the child instance would get a long list of dispensable attribute names. How to replace the Parent.all_content_attributes? Guess i need some kind of metaprogramming here?!

Berlin_J
  • 287
  • 3
  • 12

2 Answers2

4

Here is my solution:

  store :content_store, coder: JSON

  after_initialize :add_accessors_for_content_attributes

  def add_accessors_for_content_attributes
    content_attributes.each do |attr_name|
      singleton_class.class_eval do
        store_accessor :content_store, attr_name
      end
    end
  end

  def content_attributes
    parent.content_attributes.map(&:name)
  end
Berlin_J
  • 287
  • 3
  • 12
1

If I understand correctly, essentially you need to perform a database lookup for the parent content_attributes upon instantiation of your child object, and then assign the accessors dynamically based on that data.

Something along these lines could work - How do I set an attr_accessor for a dynamic instance variable?

You could try an after_initialize callback that does the lookup and then calls store_accessor on the singleton class.

metahamza
  • 1,255
  • 9
  • 22
  • Isn't it a problem, that i have to define the accessors during or before initialization, since i already need those during initialization, i.e. Child.new(color:...)? But anyways, i will give it a try! – Berlin_J Aug 22 '17 at 17:39