Module: Acfs::Resource::Attributes

Extended by:
ActiveSupport::Concern
Includes:
ActiveModel::AttributeMethods
Included in:
Acfs::Resource
Defined in:
lib/acfs/resource/attributes.rb,
lib/acfs/resource/attributes/base.rb,
lib/acfs/resource/attributes/dict.rb,
lib/acfs/resource/attributes/list.rb,
lib/acfs/resource/attributes/uuid.rb,
lib/acfs/resource/attributes/float.rb,
lib/acfs/resource/attributes/string.rb,
lib/acfs/resource/attributes/boolean.rb,
lib/acfs/resource/attributes/integer.rb,
lib/acfs/resource/attributes/date_time.rb

Overview

Acfs Attributes

Allows to specify attributes of a class with default values and type safety.

For each attribute a setter and getter will be created and values will be type casted when set.

Examples:

class User < Acfs::Resource
  attribute :name, :string, default: 'Anon'
  attribute :age, :integer
  attribute :special, My::Special::Type
end

Defined Under Namespace

Modules: ClassMethods Classes: Base, Boolean, DateTime, Dict, Float, Integer, List, String, UUID

Constant Summary collapse

Uuid =

Lower-case alias for automatic type lookup

UUID

Instance Method Summary collapse

Instance Method Details

#attributesHashWithIndifferentAccess{Symbol => Object}

Returns ActiveModel compatible list of attributes and values.

rubocop:disable Naming/MemoizedInstanceVariableName

Examples:

class User < Acfs::Resource
  attribute :name, type: String, default: 'Anon'
end
user = User.new(name: 'John')
user.attributes # => { "name" => "John" }

Returns:

  • (HashWithIndifferentAccess{Symbol => Object})

    Attributes and their values.



52
53
54
# File 'lib/acfs/resource/attributes.rb', line 52

def attributes
  @_attrs ||= HashWithIndifferentAccess.new
end

#attributes=(attributes) ⇒ Object

Update all attributes with given hash. Attribute values will be casted to defined attribute type.

Examples:

user.attributes = { :name => 'Adam' }
user.name # => 'Adam'

Parameters:

  • Attributes (Hash{String, Symbol => Object}, #each{|key, value|})

    to set in resource.

See Also:



70
71
72
# File 'lib/acfs/resource/attributes.rb', line 70

def attributes=(attributes)
  write_attributes attributes
end

#initialize(*attrs) ⇒ Object

Write default attributes defined in resource class.



31
32
33
34
35
# File 'lib/acfs/resource/attributes.rb', line 31

def initialize(*attrs)
  write_attributes self.class.attributes
  reset_changes
  super
end

#read_attribute(name) ⇒ Object

Read an attribute from instance variable.

Parameters:

  • name (Symbol, String)

    Attribute name.

Returns:

  • (Object)

    Attribute value.



81
82
83
# File 'lib/acfs/resource/attributes.rb', line 81

def read_attribute(name)
  attributes[name.to_s]
end

#write_attribute(name, value, opts = {}) ⇒ Object

Write single attribute with given value. Value will be casted to defined attribute type.

Parameters:

  • name (String, Symbol)

    Attribute name.

  • value (Object)

    Value to write.

Raises:

  • (ArgumentError)

    If no attribute with given name is defined.



161
162
163
164
165
166
167
168
# File 'lib/acfs/resource/attributes.rb', line 161

def write_attribute(name, value, opts = {})
  attr_type = self.class.defined_attributes[name.to_s]
  if attr_type
    write_raw_attribute name, attr_type.cast(value), opts
  else
    write_raw_attribute name, value, opts
  end
end

#write_attributes(attributes, opts = {}) ⇒ Object

Write a hash of attributes and values.

If attribute value is a Proc it will be evaluated in the context of the resource after all non-proc attribute values are set. Values will be casted to defined attribute type.

The behavior is used to apply default attributes from resource class definition.

Examples:

user.write_attributes name: 'john', email: ->{ "#{name}@example.org" }
user.name  # => 'john'
user.email # => '[email protected]'

Parameters:

  • Attributes (Hash{String, Symbol => Object, Proc}, #each{|key, value|})

    to write.

See Also:



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/acfs/resource/attributes.rb', line 106

def write_attributes(attributes, opts = {})
  unless attributes.respond_to?(:each) && attributes.respond_to?(:keys)
    return false
  end

  if opts.fetch(:unknown, :ignore) == :raise
    if (attributes.keys.map(&:to_s) - self.class.attributes.keys).any?
      missing = attributes.keys - self.class.attributes.keys
      missing.map!(&:inspect)
      raise ArgumentError.new "Unknown attributes: #{missing.join(', ')}"
    end
  end

  procs = {}

  attributes.each do |key, _|
    if attributes[key].is_a? Proc
      procs[key] = attributes[key]
    else
      write_local_attribute key, attributes[key], opts
    end
  end

  procs.each do |key, proc|
    write_local_attribute key, instance_exec(&proc), opts
  end

  true
end

#write_local_attribute(name, value, opts = {}) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Check if a public getter for attribute exists that should be called to write it or of #write_attribute should be called directly. This is necessary as #write_attribute should go though setters but can also handle unknown attribute that will not have a generated setter method.



143
144
145
146
147
148
149
150
# File 'lib/acfs/resource/attributes.rb', line 143

def write_local_attribute(name, value, opts = {})
  method = "#{name}="
  if respond_to? method, true
    public_send method, value
  else
    write_attribute name, value, opts
  end
end

#write_raw_attribute(name, value, _ = {}) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Write an attribute without checking type or existence or casting value to attributes type. Value be stored in an instance variable named after attribute name.

Parameters:

  • name (String, Symbol)

    Attribute name.

  • value (Object)

    Attribute value.



179
180
181
# File 'lib/acfs/resource/attributes.rb', line 179

def write_raw_attribute(name, value, _ = {})
  attributes[name.to_s] = value
end