Using Ruby 3.1.1.
Trying to implement similar to: https://github.com/mongodb/mongoid/blob/master/lib/mongoid/fields.rb :: class_attribute :fields
When I include a model concern on a parent model the class_attributes seem to get merged on child models. I wanted to maintain a seperate class_attribute hash on each child class, like the mongoid Field concern does.
This only seems to occur when inheriting.
module Dashboardable
extend ActiveSupport::Concern
included do
class_attribute :dashboard_fields
self.dashboard_fields = {}
end
class_methods do
def dashboard_field(name, options = {})
dashboard_fields[name] = options.merge(klass: self)
end
end
end
class Person
include Mongoid::Document
include Dashboardable
dashboard_field :first_name
end
class Foo < Person
dashboard_field :foot
field :foot, type: String
end
class Bar < Person
dashboard_field :bart
field :bart, type: String
end
Foo.dashboard_fields: [:first_name, :foot]
Bar.dashboard_fields: [:first_name, :foot, :bart]
Foo.fields: ["_id", "_type", "foot"]
Bar.fields: ["_id", "_type", "bart"]
CodePudding user response:
I took a lot of edits and some digging to figure out the question and whats going on. Sorry.
Whats happening is that with class_attribute
is that all the classes are actually sharing the same object in thier instance attributes. This is an intended behavior.
You can actually get it to work with class_attribute
if you make sure that each subclass gets a duplicate of the "parent hash":
module Dashboardable
extend ActiveSupport::Concern
included do
class_attribute :dashboard_fields, default: {}
end
class_methods do
def inherited(subclass)
subclass.class_eval { self.dashboard_fields = superclass.dashboard_fields.dup }
end
def dashboard_field(name, options = {})
dashboard_fields[name] = options.merge(klass: self)
end
end
end