class Virtus::AttributeSet

A set of Attribute objects

Public Class Methods

create(descendant) click to toggle source

@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
new(parent = nil, attributes = []) click to toggle source

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

<<(attribute) click to toggle source

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
[](name) click to toggle source

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
[]=(name, attribute) click to toggle source

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) click to toggle source

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
define_reader_method(attribute, method_name, visibility) click to toggle source

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
define_writer_method(attribute, method_name, visibility) click to toggle source

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
each() { |attribute| ... } click to toggle source

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
finalize() click to toggle source

@api private

# File lib/virtus/attribute_set.rb, line 202
def finalize
  each do |attribute|
    self << attribute.finalize unless attribute.finalized?
  end
end
get(object) click to toggle source

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
merge(attributes) click to toggle source

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() click to toggle source

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
set(object, attributes) click to toggle source

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_defaults(object, filter = method(:skip_default?)) click to toggle source

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_attributes(attributes) click to toggle source

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
skip_default?(object, attribute) click to toggle source

@api private

# File lib/virtus/attribute_set.rb, line 211
def skip_default?(object, attribute)
  attribute.lazy? || attribute.defined?(object)
end
update_index(name, attribute) click to toggle source

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