From 38e695037cb736196af05e0f4587742915ceee89 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 15 Jan 2005 13:52:58 +0000 Subject: Added availability of class inheritable attributes to the masses #477 [bitsweat] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@412 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activesupport/lib/class_inheritable_attributes.rb | 137 ++++++++++++++++------ 1 file changed, 104 insertions(+), 33 deletions(-) (limited to 'activesupport/lib') 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 -- cgit v1.2.3