Basic Group Model:
class Group < ActiveRecord::Base
@@ItemType = 'GroupItem' # Base ItemType
after_initialize :default_item_type
has_many :group_assignments
has_many :items, through: :group_assignments, source: :groupable, source_type: @@ItemType, dependent: :destroy
accepts_nested_attributes_for :items, allow_destroy: true
private
def default_item_type
self.item_type = @@ItemType if self.new_record?
end
end
Namespaced Model:
class Gradation::Group < Group
@@ItemType = 'Gradation' # Base ItemType
after_initialize :default_item_type
has_many :group_assignments
has_many :items, through: :group_assignments, source: :groupable, source_type: @@ItemType, dependent: :destroy
accepts_nested_attributes_for :items, allow_destroy: true
private
def default_item_type
self.item_type = @@ItemType if self.new_record?
end
end
I am attempting to have a field *item_type* be set on the *after_initialize* callback, but not matter what I do, the callback is only triggered on the regular group model and not the namespaced one.
I am struggling to understand why this is the expected behavior, and also how to get callbacks to work for the namespaced Group .
Using the class variable here @@ItemType = 'Gradation'
is not likely to help you out. In an initial modeling of this problem, the @@ItemType were stepping on each other, always giving you 'Gradation'
The following will work. You'll notice the differences:
app/models/group.rb
class Group < ActiveRecord::Base
ITEM_TYPE = 'GroupItem' # Base ItemType
after_initialize :default_item_type
private
def default_item_type
self.item_type = ITEM_TYPE if self.new_record?
end
end
app/models/group/gradation.rb
class Group::Gradation < Group
ITEM_TYPE = 'Gradation' # Base ItemType
private
def default_item_type
self.item_type = ITEM_TYPE if self.new_record?
end
end
Notes:
default_item_type
on each subclass so that it can pull the correct ITEM_TYPE To get rid of #2 above, you could do this:
class Group < ActiveRecord::Base
ITEM_TYPE = 'GroupItem' # Base ItemType
after_initialize :default_item_type
private
def default_item_type
self.item_type = "#{self.class}::ITEM_TYPE".constantize if self.new_record?
end
end
Then, each subclass could be:
class Group::Graduation < Group
ITEM_TYPE = 'Graduation' # Base ItemType
end
The overall solution to my problem looks like this...
Base Group Model:
class Group < ActiveRecord::Base
@@ItemType = 'GroupItem' # Base ItemType
after_initialize :default_item_type
has_many :group_assignments
has_many :items, through: :group_assignments, source: :groupable, source_type: @@ItemType, dependent: :destroy
accepts_nested_attributes_for :items, allow_destroy: true
private
def default_item_type
self.item_type = @@ItemType if self.new_record?
end
end
Subclassed Group model with ItemType set to another arbitrary model (in app/models/groups/gradation_group.rb):
class Groups::GradationGroup < Group
@@ItemType = 'Gradation'
has_many :items, through: :group_assignments, source: :groupable, source_type: @@ItemType, dependent: :destroy
end
My understanding is I had to change the namespace to something that is not a class name. I also had to change the group name to something other than what the items association will be composed of (in this case Gradation ).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.