class Virtus::AttributeSet
A set of Attribute objects
Public Class Methods
@api private
# File lib/virtus/attribute_set.rb, line 8 def self.create(descendant) if descendant.respond_to?(:superclass) && descendant.superclass.respond_to?(:attribute_set) parent = descendant.superclass.public_send(:attribute_set) end descendant.instance_variable_set('@attribute_set', AttributeSet.new(parent)) end
Initialize an AttributeSet
@param [AttributeSet] parent @param [Array] attributes
@return [undefined]
@api private
# File lib/virtus/attribute_set.rb, line 23 def initialize(parent = nil, attributes = []) @parent = parent @attributes = attributes.dup @index = {} reset end
Public Instance Methods
Adds an attribute to the set
@example
attribute_set << attribute
@param [Attribute] attribute
@return [self]
@api public
# File lib/virtus/attribute_set.rb, line 75 def <<(attribute) self[attribute.name] = attribute attribute.define_accessor_methods(self) if attribute.finalized? self end
Get an attribute by name
@example
attribute_set[:name] # => Attribute object
@param [Symbol] name
@return [Attribute]
@api public
# File lib/virtus/attribute_set.rb, line 91 def [](name) @index[name] end
Set an attribute by name
@example
attribute_set[:name] = attribute
@param [Symbol] name @param [Attribute] attribute
@return [Attribute]
@api public
# File lib/virtus/attribute_set.rb, line 106 def []=(name, attribute) @attributes << attribute update_index(name, attribute) end
Coerce attributes received to a hash
@return [Hash]
@api private
# File lib/virtus/attribute_set.rb, line 195 def coerce(attributes) ::Hash.try_convert(attributes) or raise( NoMethodError, "Expected #{attributes.inspect} to respond to #to_hash" ) end
Defines an attribute reader method
@param [Attribute] attribute @param [Symbol] method_name @param [Symbol] visibility
@return [undefined]
@api private
# File lib/virtus/attribute_set.rb, line 131 def define_reader_method(attribute, method_name, visibility) define_method(method_name) { attribute.get(self) } send(visibility, method_name) end
Defines an attribute writer method
@param [Attribute] attribute @param [Symbol] method_name @param [Symbol] visibility
@return [undefined]
@api private
# File lib/virtus/attribute_set.rb, line 145 def define_writer_method(attribute, method_name, visibility) define_method(method_name) { |value| attribute.set(self, value) } send(visibility, method_name) end
Iterate over each attribute in the set
@example
attribute_set = AttributeSet.new(attributes, parent) attribute_set.each { |attribute| ... }
@yield [attribute]
@yieldparam [Attribute] attribute
each attribute in the set
@return [self]
@api public
# File lib/virtus/attribute_set.rb, line 44 def each return to_enum unless block_given? @index.each { |name, attribute| yield attribute if name.kind_of?(Symbol) } self end
@api private
# File lib/virtus/attribute_set.rb, line 202 def finalize each do |attribute| self << attribute.finalize unless attribute.finalized? end end
Get values of all attributes defined for this class, ignoring privacy
@return [Hash]
@api private
# File lib/virtus/attribute_set.rb, line 155 def get(object) each_with_object({}) do |attribute, attributes| name = attribute.name attributes[name] = object.__send__(name) if attribute.public_reader? end end
Adds the attributes to the set
@example
attribute_set.merge(attributes)
@param [Array<Attribute>] attributes
@return [self]
@api public
# File lib/virtus/attribute_set.rb, line 60 def merge(attributes) attributes.each { |attribute| self << attribute } self end
Reset the index when the parent is updated
@return [self]
@api private
# File lib/virtus/attribute_set.rb, line 116 def reset merge_attributes(@parent) if @parent merge_attributes(@attributes) self end
Mass-assign attribute values
@see Virtus::InstanceMethods#attributes=
@return [Hash]
@api private
# File lib/virtus/attribute_set.rb, line 169 def set(object, attributes) coerce(attributes).each do |name, value| writer_name = "#{name}=" if object.allowed_writer_methods.include?(writer_name) object.__send__(writer_name, value) end end end
Set default attributes
@return [self]
@api private
# File lib/virtus/attribute_set.rb, line 183 def set_defaults(object, filter = method(:skip_default?)) each do |attribute| next if filter.call(object, attribute) attribute.set_default_value(object) end end
Private Instance Methods
Merge the attributes into the index
@param [Array<Attribute>] attributes
@return [undefined]
@api private
# File lib/virtus/attribute_set.rb, line 222 def merge_attributes(attributes) attributes.each { |attribute| update_index(attribute.name, attribute) } end
@api private
# File lib/virtus/attribute_set.rb, line 211 def skip_default?(object, attribute) attribute.lazy? || attribute.defined?(object) end
Update the symbol and string indexes with the attribute
@param [Symbol] name
@param [Attribute] attribute
@return [undefined]
@api private
# File lib/virtus/attribute_set.rb, line 235 def update_index(name, attribute) @index[name] = @index[name.to_s.freeze] = attribute end