Upgraded Rails and RSpec
[monkeycharger.git] / vendor / rails / activesupport / lib / active_support / core_ext / class / inheritable_attributes.rb
blob371d074d3404790f8aeadd97f7d3ccb6211fc015
1 # Retain for backward compatibility.  Methods are now included in Class.
2 module ClassInheritableAttributes # :nodoc:
3 end
5 # Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of
6 # their parents' attributes, instead of just a pointer to the same. This means that the child can add elements
7 # to, for example, an array without those additions being shared with either their parent, siblings, or
8 # children, which is unlike the regular class-level attributes that are shared across the entire hierarchy.
9 class Class # :nodoc:
10   def class_inheritable_reader(*syms)
11     syms.each do |sym|
12       next if sym.is_a?(Hash)
13       class_eval <<-EOS
14         def self.#{sym}
15           read_inheritable_attribute(:#{sym})
16         end
18         def #{sym}
19           self.class.#{sym}
20         end
21       EOS
22     end
23   end
25   def class_inheritable_writer(*syms)
26     options = syms.extract_options!
27     syms.each do |sym|
28       class_eval <<-EOS
29         def self.#{sym}=(obj)
30           write_inheritable_attribute(:#{sym}, obj)
31         end
33         #{"
34         def #{sym}=(obj)
35           self.class.#{sym} = obj
36         end
37         " unless options[:instance_writer] == false }
38       EOS
39     end
40   end
42   def class_inheritable_array_writer(*syms)
43     options = syms.extract_options!
44     syms.each do |sym|
45       class_eval <<-EOS
46         def self.#{sym}=(obj)
47           write_inheritable_array(:#{sym}, obj)
48         end
50         #{"
51         def #{sym}=(obj)
52           self.class.#{sym} = obj
53         end
54         " unless options[:instance_writer] == false }
55       EOS
56     end
57   end
59   def class_inheritable_hash_writer(*syms)
60     options = syms.extract_options!
61     syms.each do |sym|
62       class_eval <<-EOS
63         def self.#{sym}=(obj)
64           write_inheritable_hash(:#{sym}, obj)
65         end
67         #{"
68         def #{sym}=(obj)
69           self.class.#{sym} = obj
70         end
71         " unless options[:instance_writer] == false }
72       EOS
73     end
74   end
76   def class_inheritable_accessor(*syms)
77     class_inheritable_reader(*syms)
78     class_inheritable_writer(*syms)
79   end
81   def class_inheritable_array(*syms)
82     class_inheritable_reader(*syms)
83     class_inheritable_array_writer(*syms)
84   end
86   def class_inheritable_hash(*syms)
87     class_inheritable_reader(*syms)
88     class_inheritable_hash_writer(*syms)
89   end
91   def inheritable_attributes
92     @inheritable_attributes ||= EMPTY_INHERITABLE_ATTRIBUTES
93   end
94   
95   def write_inheritable_attribute(key, value)
96     if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
97       @inheritable_attributes = {}
98     end
99     inheritable_attributes[key] = value
100   end
101   
102   def write_inheritable_array(key, elements)
103     write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil?
104     write_inheritable_attribute(key, read_inheritable_attribute(key) + elements)
105   end
107   def write_inheritable_hash(key, hash)
108     write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil?
109     write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash))
110   end
112   def read_inheritable_attribute(key)
113     inheritable_attributes[key]
114   end
115   
116   def reset_inheritable_attributes
117     @inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
118   end
120   private
121     # Prevent this constant from being created multiple times
122     EMPTY_INHERITABLE_ATTRIBUTES = {}.freeze unless const_defined?(:EMPTY_INHERITABLE_ATTRIBUTES)
124     def inherited_with_inheritable_attributes(child)
125       inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes)
126       
127       if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
128         new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
129       else
130         new_inheritable_attributes = inheritable_attributes.inject({}) do |memo, (key, value)|
131           memo.update(key => (value.dup rescue value))
132         end
133       end
134       
135       child.instance_variable_set('@inheritable_attributes', new_inheritable_attributes)
136     end
138     alias inherited_without_inheritable_attributes inherited
139     alias inherited inherited_with_inheritable_attributes