diff options
Diffstat (limited to 'activesupport/lib')
-rw-r--r-- | activesupport/lib/class_inheritable_attributes.rb | 137 |
1 files changed, 104 insertions, 33 deletions
diff --git a/activesupport/lib/class_inheritable_attributes.rb b/activesupport/lib/class_inheritable_attributes.rb index 5ad5a362f6..f9ca7af7b2 100644 --- a/activesupport/lib/class_inheritable_attributes.rb +++ b/activesupport/lib/class_inheritable_attributes.rb @@ -1,46 +1,117 @@ +# Retain for backward compatibility. Methods are now included in Class. +module ClassInheritableAttributes # :nodoc: +end + # Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of # their parents' attributes, instead of just a pointer to the same. This means that the child can add elements # to, for example, an array without those additions being shared with either their parent, siblings, or # children, which is unlike the regular class-level attributes that are shared across the entire hierarchy. -module ClassInheritableAttributes # :nodoc: - def self.append_features(base) - super - base.extend(ClassMethods) - end - - module ClassMethods # :nodoc: - @@classes ||= {} - - def inheritable_attributes - @@classes[self] ||= {} - end - - def write_inheritable_attribute(key, value) - inheritable_attributes[key] = value - end - - def write_inheritable_array(key, elements) - write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil? - write_inheritable_attribute(key, read_inheritable_attribute(key) + elements) +class Class # :nodoc: + def class_inheritable_reader(*syms) + syms.each do |sym| + class_eval <<-EOS + def self.#{sym} + read_inheritable_attribute(:#{sym}) + end + + def #{sym} + self.class.#{sym} + end + EOS end + end - def write_inheritable_hash(key, hash) - write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil? - write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash)) + def class_inheritable_writer(*syms) + syms.each do |sym| + class_eval <<-EOS + def self.#{sym}=(obj) + write_inheritable_attribute(:#{sym}, obj) + end + + def #{sym}=(obj) + self.class.#{sym} = obj + end + EOS end + end + + def class_inheritable_array_writer(*syms) + syms.each do |sym| + class_eval <<-EOS + def self.#{sym}=(obj) + write_inheritable_array(:#{sym}, obj) + end - def read_inheritable_attribute(key) - inheritable_attributes[key] + def #{sym}=(obj) + self.class.#{sym} = obj + end + EOS end - - def reset_inheritable_attributes - inheritable_attributes.clear + end + + def class_inheritable_hash_writer(*syms) + syms.each do |sym| + class_eval <<-EOS + def self.#{sym}=(obj) + write_inheritable_hash(:#{sym}, obj) + end + + def #{sym}=(obj) + self.class.#{sym} = obj + end + EOS end + end + + def class_inheritable_accessor(*syms) + class_inheritable_reader(*syms) + class_inheritable_writer(*syms) + end - private - def inherited(child) - @@classes[child] = inheritable_attributes.dup - end - + def class_inheritable_array(*syms) + class_inheritable_reader(*syms) + class_inheritable_array_writer(*syms) end + + def class_inheritable_hash(*syms) + class_inheritable_reader(*syms) + class_inheritable_hash_writer(*syms) + end + + def inheritable_attributes + @inheritable_attributes ||= {} + end + + def write_inheritable_attribute(key, value) + inheritable_attributes[key] = value + end + + def write_inheritable_array(key, elements) + write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil? + write_inheritable_attribute(key, read_inheritable_attribute(key) + elements) + end + + def write_inheritable_hash(key, hash) + write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil? + write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash)) + end + + def read_inheritable_attribute(key) + inheritable_attributes[key] + end + + def reset_inheritable_attributes + inheritable_attributes.clear + end + + private + def inherited_with_inheritable_attributes(child) + inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes) + child.instance_variable_set('@inheritable_attributes', inheritable_attributes.dup) + end + + if respond_to?(:inherited) + alias_method :inherited_without_inheritable_attributes, :inherited + end + alias_method :inherited, :inherited_with_inheritable_attributes end |