diff options
| -rw-r--r-- | activesupport/CHANGELOG | 18 | ||||
| -rw-r--r-- | activesupport/lib/class_inheritable_attributes.rb | 137 | 
2 files changed, 122 insertions, 33 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 15f48046b9..ecc9a75929 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,3 +1,21 @@ +* Added availability of class inheritable attributes to the masses #477 [bitsweat] + +    class Foo +      class_inheritable_reader :read_me +      class_inheritable_writer :write_me +      class_inheritable_accessor :read_and_write_me +      class_inheritable_array :read_and_concat_me +      class_inheritable_hash :read_and_update_me +    end + +    # Bar gets a clone of (not a reference to) Foo's attributes. +    class Bar < Foo +    end + +    Bar.read_and_write_me == Foo.read_and_write_me +    Bar.read_and_write_me = 'bar' +    Bar.read_and_write_me != Foo.read_and_write_me +  * Added Inflections as an extension on String, so Inflector.pluralize(Inflector.classify(name)) becomes name.classify.pluralize #476 [bitsweat]  * Added Byte operations to Numeric, so 5.5.megabytes + 200.kilobytes #461 [Marcel Molina] 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  | 
