module Acfs::Resource::Attributes
Acfs
Attributes
¶ ↑
Allows to specify attributes of a class with default values and type safety.
@example
class User < Acfs::Resource attribute :name, :string, default: 'Anon' attribute :age, :integer attribute :special, My::Special::Type end
For each attribute a setter and getter will be created and values will be type casted when set.
Constants
- Uuid
@api public
UUID
attribute type. Use it in your model as an attribute type:@example
class User < Acfs::Resource attribute :id, :uuid end
Public Class Methods
@api public
Write default attributes defined in resource class.
@see write_attributes
@see ClassMethods#attributes
# File lib/acfs/resource/attributes.rb, line 31 def initialize(*attrs) write_attributes self.class.attributes reset_changes super end
Public Instance Methods
@api public
Returns ActiveModel compatible list of attributes and values.
@example
class User < Acfs::Resource attribute :name, type: String, default: 'Anon' end user = User.new(name: 'John') user.attributes # => { "name" => "John" }
@return [HashWithIndifferentAccess{Symbol => Object}]
Attributes and their values.
rubocop:disable Naming/MemoizedInstanceVariableName
# File lib/acfs/resource/attributes.rb, line 52 def attributes @_attrs ||= HashWithIndifferentAccess.new end
@api public
Update all attributes with given hash. Attribute values will be casted to defined attribute type.
@example
user.attributes = { :name => 'Adam' } user.name # => 'Adam'
@param [Hash{String, Symbol => Object}, each{|key, value|}]
Attributes to set in resource.
@see write_attributes
Delegates attributes hash to {#write_attributes}.
# File lib/acfs/resource/attributes.rb, line 70 def attributes=(attributes) write_attributes(attributes) end
@api public
Read an attribute from instance variable.
@param [Symbol, String] name Attribute name. @return [Object] Attribute value.
# File lib/acfs/resource/attributes.rb, line 81 def read_attribute(name) attributes[name.to_s] end
@api public
Write single attribute with given value. Value will be casted to defined attribute type.
@param [String, Symbol] name Attribute name. @param [Object] value Value to write. @raise [ArgumentError] If no attribute with given name is defined.
# File lib/acfs/resource/attributes.rb, line 160 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
@api public
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.
@example
user.write_attributes name: 'john', email: ->{ "#{name}@example.org" } user.name # => 'john' user.email # => 'john@example.org'
@param [Hash{String, Symbol => Object, Proc}, each{|key, value|}]
Attributes to write.
@see write_attribute
Delegates attribute values to `#write_attribute`.
# 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 && (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 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
@api private
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.
# File lib/acfs/resource/attributes.rb, line 142 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
@api private
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.
@param [String, Symbol] name Attribute name. @param [Object] value Attribute value.
# File lib/acfs/resource/attributes.rb, line 178 def write_raw_attribute(name, value, _ = {}) attributes[name.to_s] = value end