0
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
0
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0
# Allows attributes to be shared within an inheritance hierarchy, but where
0
# each descendant gets a copy of their parents' attributes, instead of just a
0
# pointer to the same. This means that the child can add elements to, for
0
@@ -39,7 +38,7 @@ class Class
0
def cattr_reader(*syms)
0
syms.flatten.each do |sym|
0
next if sym.is_a?(Hash)
0
- class_eval(<<-
EOS, __FILE__, __LINE__)
0
+ class_eval(<<-
RUBY, __FILE__, __LINE__ + 1)
0
unless defined? @@#{sym}
0
@@ -51,7 +50,7 @@ class Class
0
@@ -65,7 +64,7 @@ class Class
0
def cattr_writer(*syms)
0
options = syms.last.is_a?(Hash) ? syms.pop : {}
0
syms.flatten.each do |sym|
0
- class_eval(<<-RUBY, __FILE__, __LINE__
)
0
+ class_eval(<<-RUBY, __FILE__, __LINE__
+ 1)
0
unless defined? @@#{sym}
0
@@ -76,7 +75,7 @@ class Class
0
unless options[:instance_writer] == false
0
- class_eval(<<-RUBY, __FILE__, __LINE__
)
0
+ class_eval(<<-RUBY, __FILE__, __LINE__
+ 1)
0
@@ -110,22 +109,28 @@ class Class
0
# (error out or do the same as other methods above) instead of silently
0
# moving on). In particular, this makes the return value of this function
0
- def class_inheritable_reader(*syms)
0
- next if sym.is_a?(Hash)
0
- class_eval <<-EOS, __FILE__, __LINE__
0
- read_inheritable_attribute(:#{sym})
0
+ def class_inheritable_reader(*ivars)
0
+ instance_reader = ivars.pop[:reader] if ivars.last.is_a?(Hash)
0
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
0
+ return @#{ivar} if self == #{self} || defined?(@#{ivar})
0
+ ivar = superclass.#{ivar}
0
+ return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}")
0
+ @#{ivar} = ivar ? ivar.dup : ivar
0
+ unless instance_reader == false
0
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
0
# Defines class-level inheritable attribute writer. Attributes are available to subclasses,
0
# each subclass has a copy of parent's attribute.
0
@@ -138,83 +143,22 @@ class Class
0
# @todo We need a style for class_eval <<-HEREDOC. I'd like to make it
0
# class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere.
0
- def class_inheritable_writer(*syms)
0
- options = syms.last.is_a?(Hash) ? syms.pop : {}
0
- class_eval(<<-RUBY, __FILE__, __LINE__)
0
- write_inheritable_attribute(:#{sym}, obj)
0
- unless options[:instance_writer] == false
0
- class_eval <<-RUBY, __FILE__, __LINE__
0
- self.class.#{sym} = obj
0
- # Defines class-level inheritable array writer. Arrays are available to subclasses,
0
- # each subclass has a copy of parent's array. Difference between other inheritable
0
- # attributes is that array is recreated every time it is written.
0
- # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of array attribute
0
- # names to define inheritable writer for.
0
- # @option syms :instance_writer<Boolean> if true, instance-level inheritable array
0
- # attribute writer is defined.
0
- # @return <Array[#to_s]> An array of the attributes that were made into inheritable
0
- def class_inheritable_array_writer(*syms)
0
- options = syms.last.is_a?(Hash) ? syms.pop : {}
0
- class_eval(<<-RUBY, __FILE__, __LINE__)
0
- write_inheritable_array(:#{sym}, obj)
0
+ def class_inheritable_writer(*ivars)
0
+ instance_writer = ivars.pop[:instance_writer] if ivars.last.is_a?(Hash)
0
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
0
+ def self.#{ivar}=(obj)
0
- unless options[:instance_writer] == false
0
- class_eval(<<-RUBY, __FILE__, __LINE__)
0
- self.class.#{sym} = obj
0
- # Defines class-level inheritable hash writer. Hashs are available to subclasses,
0
- # each subclass has a copy of parent's hash. Difference between other inheritable
0
- # attributes is that hash is recreated every time it is written.
0
- # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]>:: Array of hash
0
- # attribute names to define inheritable writer for.
0
- # @option syms :instance_writer<Boolean>:: if true, instance-level inheritable hash
0
- # attribute writer is defined.
0
- # @return <Array[#to_s]> An Array of attributes turned into hash_writers.
0
- def class_inheritable_hash_writer(*syms)
0
- options = syms.last.is_a?(Hash) ? syms.pop : {}
0
- class_eval(<<-RUBY, __FILE__, __LINE__)
0
- write_inheritable_hash(:#{sym}, obj)
0
- unless options[:instance_writer] == false
0
- class_eval(<<-RUBY, __FILE__, __LINE__)
0
- self.class.#{sym} = obj
0
+ unless instance_writer == false
0
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
0
+ def #{ivar}=(obj) self.class.#{ivar} = obj end
0
# Defines class-level inheritable attribute accessor. Attributes are available to subclasses,
0
# each subclass has a copy of parent's attribute.
0
@@ -228,136 +172,4 @@ class Class
0
class_inheritable_reader(*syms)
0
class_inheritable_writer(*syms)
0
- # Defines class-level inheritable array accessor. Arrays are available to subclasses,
0
- # each subclass has a copy of parent's array. Difference between other inheritable
0
- # attributes is that array is recreated every time it is written.
0
- # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of array attribute
0
- # names to define inheritable accessor for.
0
- # @option syms :instance_writer<Boolean> if true, instance-level inheritable array
0
- # attribute writer is defined.
0
- # @return <Array[#to_s]> An Array of attributes turned into inheritable arrays.
0
- def class_inheritable_array(*syms)
0
- class_inheritable_reader(*syms)
0
- class_inheritable_array_writer(*syms)
0
- # Defines class-level inheritable hash accessor. Hashs are available to subclasses,
0
- # each subclass has a copy of parent's hash. Difference between other inheritable
0
- # attributes is that hash is recreated every time it is written.
0
- # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of hash attribute
0
- # names to define inheritable accessor for.
0
- # @option syms :instance_writer<Boolean> if true, instance-level inheritable hash
0
- # attribute writer is defined.
0
- # @return <Array[#to_s]> An Array of attributes turned into inheritable hashes.
0
- def class_inheritable_hash(*syms)
0
- class_inheritable_reader(*syms)
0
- class_inheritable_hash_writer(*syms)
0
- # @return <Hash> inheritable attributes hash or it's default value, new frozen Hash.
0
- def inheritable_attributes
0
- @inheritable_attributes ||= EMPTY_INHERITABLE_ATTRIBUTES
0
- # Sets the attribute which copy is available to subclasses.
0
- # @param key<#to_s> inheritable attribute name
0
- # @param value<not(Array, Hash)> value of inheritable attribute
0
- # @return <not(Array, Hash)> the value that was set
0
- # If inheritable attributes storage has it's default value,
0
- # a new frozen hash, it is set to new Hash that is not frozen.
0
- def write_inheritable_attribute(key, value)
0
- if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
0
- @inheritable_attributes = {}
0
- inheritable_attributes[key] = value
0
- # Sets the array attribute which copy is available to subclasses.
0
- # @param key<#to_s> inheritable attribute name
0
- # @param elements<Array> value of inheritable attribute
0
- # @return <Array> the Array that was set
0
- # Inheritable array is re-created on each write.
0
- def write_inheritable_array(key, elements)
0
- write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil?
0
- write_inheritable_attribute(key, read_inheritable_attribute(key) + elements)
0
- # Sets the hash attribute which copy is available to subclasses.
0
- # @param key<#to_s> inheritable attribute name
0
- # @param value<Hash> value of inheritable attribute
0
- # @return <Hash> the new hash that resulted from merging the new values
0
- # with the inherited values.
0
- # Inheritable hash is re-created on each write.
0
- def write_inheritable_hash(key, hash)
0
- write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil?
0
- write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash))
0
- # Reads value of inheritable attributes.
0
- # @param key<#to_s> the key of the attribute to read
0
- # Inheritable attribute value. Subclasses store copies of values.
0
- def read_inheritable_attribute(key)
0
- inheritable_attributes[key]
0
- # Resets inheritable attributes.
0
- # @return <Object> the empty inheritable attributes. By default, this
0
- # is a frozen, empty Hash. You can override this for a class by defining
0
- # EMPTY_INHERITABLE_ATTRIBUTES
0
- # @todo do we need this?
0
- def reset_inheritable_attributes
0
- @inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
0
- # Prevent this constant from being created multiple times
0
- EMPTY_INHERITABLE_ATTRIBUTES = {}.freeze unless const_defined?(:EMPTY_INHERITABLE_ATTRIBUTES)
0
- def inherited_with_inheritable_attributes(child)
0
- inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes)
0
- if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
0
- new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
0
- new_inheritable_attributes = inheritable_attributes.inject({}) do |memo, (key, value)|
0
- memo.update(key => ((value.is_a?(Module) ? value : value.dup) rescue value))
0
- child.instance_variable_set('@inheritable_attributes', new_inheritable_attributes)
0
- alias inherited_without_inheritable_attributes inherited
0
- alias inherited inherited_with_inheritable_attributes
Comments
No one has commented yet.