File: inheritable_attr.rb

package info (click to toggle)
ruby-uber 0.1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 216 kB
  • sloc: ruby: 466; makefile: 4
file content (40 lines) | stat: -rw-r--r-- 1,078 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
module Uber
  module InheritableAttr

    def inheritable_attr(name, options={})
      instance_eval <<-RUBY, __FILE__, __LINE__ + 1
        def #{name}=(v)
          @#{name} = v
        end

        def #{name}
          return @#{name} if instance_variable_defined?(:@#{name})
          @#{name} = InheritableAttribute.inherit_for(self, :#{name}, #{options})
        end
      RUBY
    end

    def self.inherit_for(klass, name, options={})
      return unless klass.superclass.respond_to?(name)

      value = klass.superclass.send(name) # could be nil

      return value if options[:clone] == false
      Clone.(value) # this could be dynamic, allowing other inheritance strategies.
    end

    class Clone
      # The second argument allows injecting more types.
      def self.call(value, uncloneable=uncloneable())
        uncloneable.each { |klass| return value if value.kind_of?(klass) }
        value.clone
      end

      def self.uncloneable
        [Symbol, TrueClass, FalseClass, NilClass]
      end
    end
  end

  InheritableAttribute = InheritableAttr
end