Module: InheritableAttr

Defined in:
lib/inheritable_attr.rb,
lib/inheritable_attr/version.rb

Constant Summary collapse

VERSION =
"1.0.0"

Instance Method Summary collapse

Instance Method Details

#inheritable_attr(*names) ⇒ Object

Creates an inheritable attribute with accessors in the singleton class. Derived classes inherit the attributes. This is especially helpful with arrays or hashes that are extended in the inheritance chain. Note that you have to initialize the inheritable attribute. Based on github.com/apotonick/hooks/blob/master/lib/hooks/inheritable_attribute.rb

Example:

class Cat
  inheritable_attr :drinks
  self.drinks = ["Becks"]

class Garfield < Cat
  self.drinks << "Fireman's 4"

and then, later

Cat.drinks      #=> ["Becks"]
Garfield.drinks #=> ["Becks", "Fireman's 4"]

Raises:

  • (ArgumentError)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/inheritable_attr.rb', line 24

def inheritable_attr(*names)
  raise ArgumentError, 'at least one attribute must be specified' if names.empty?

  options = names.extract_options!

  names.each do |name|
    instance_eval(<<-EOS, __FILE__, __LINE__)
      def #{name}=(v)
        @#{name} = v
      end

      def #{name}
        return @#{name} unless superclass.respond_to?(:#{name}) and value = superclass.#{name}
        initial = value.duplicable? ? value.clone : value
        defined?(@#{name}) ? @#{name} : @#{name} = initial
      end
    EOS

    class_eval(<<-EOS, __FILE__, __LINE__) if options.fetch(:instance_reader, true)
      def #{name}
        @#{name} ||= self.class.#{name}.duplicable? ? self.class.#{name}.clone : self.class.#{name}
      end
    EOS

    class_eval(<<-EOS, __FILE__, __LINE__) if options.fetch(:instance_writer, true)
      def #{name}=(v)
        @#{name} = v
      end
    EOS

    send(:"#{name}=", options[:default]) if options.key?(:default)
  end
end