module Shamu::Attributes::Assignment

Provide a means for defining writable attributes.

Public Instance Methods

[]=( name, value ) click to toggle source

@param [Symbol] name of the attribute to assign. @param [Object] value to assign.

# File lib/shamu/attributes/assignment.rb, line 17
def []=( name, value )
  send :"assign_#{ name }", value if attribute?( name )
end
assigned?( name ) click to toggle source

@return [Boolean] true if the attribute as explicitly been defined - not just present/memoized.

# File lib/shamu/attributes/assignment.rb, line 33
def assigned?( name )
  assigned_attributes.include?( name )
end
assigned_attributes() click to toggle source

@return [Array<Symbol>] the attributes that have been assigned.

# File lib/shamu/attributes/assignment.rb, line 22
def assigned_attributes
  @assigned_attributes.to_a || []
end
unassigned_attributes() click to toggle source

@return [Array<Symbol>] the attributes that have not been assigned.

# File lib/shamu/attributes/assignment.rb, line 27
def unassigned_attributes
  self.class.attributes.keys - assigned_attributes
end

Private Instance Methods

assigned_attribute!( name ) click to toggle source
# File lib/shamu/attributes/assignment.rb, line 39
def assigned_attribute!( name )
  @assigned_attributes ||= Set.new
  @assigned_attributes << name
end
attribute( name, *args, **options, &block ) click to toggle source

Define a new attribute for the class.

@param (see Projection::DSL#attribute) @param [Symbol, call] coerce name of a method on the assigned value

to call, or a custom method that can parse values when assigning
the attribute.

@param [Boolean] array true if the expected value should be an array.

@return [void]

@example

class Params
  include Shamu::Attributes
  include Shamu::Attributes::Assignment

  attribute :created_at, coerce: :to_datetime
  attribute :count, coerce: :to_i
  attribute :label, coerce: ->(value){ value.upcase.to_sym }
  attribute :tags, coerce: :to_s, array: true
end
Calls superclass method
# File lib/shamu/attributes/assignment.rb, line 68
def attribute( name, *args, **options, &block )
  super( name, *args, **options )
  define_attribute_assignment( name, **options )
  define_attribute_writer( name, **options )
end
attribute_option_keys() click to toggle source
Calls superclass method
# File lib/shamu/attributes/assignment.rb, line 76
def attribute_option_keys
  super + [ :coerce, :array ]
end
cource_method( name, coerce ) click to toggle source
# File lib/shamu/attributes/assignment.rb, line 127
def cource_method( name, coerce )
  if coerce == :smart
    case name
    when /_at$/, /_on$/ then :to_datetime
    when /(^|_)ids?$/   then :to_model_id
    end
  else
    coerce
  end
end
define_attribute_array( name ) click to toggle source
# File lib/shamu/attributes/assignment.rb, line 95
          def define_attribute_array( name )
            class_eval <<-RUBY, __FILE__, __LINE__ + 1
              def coerce_#{ name }_array( value )
                value && Array( value ).map do |v|
                  coerce_#{ name }( v )
                end
              end
            RUBY

            private :"coerce_#{ name }_array"
          end
define_attribute_assignment( name, coerce: :smart, array: false, ** ) click to toggle source
Calls superclass method
# File lib/shamu/attributes/assignment.rb, line 80
          def define_attribute_assignment( name, coerce: :smart, array: false, ** )
            super

            class_eval <<-RUBY, __FILE__, __LINE__ + 1
              def assign_#{ name }( *values )
                assigned_attribute!( :#{ name } )
                @#{ name } = coerce_#{ name }#{ array ? '_array' : '' }( *values )
              end
            RUBY
            private :"assign_#{ name }"

            define_attribute_coercion( name, coerce )
            define_attribute_array( name ) if array
          end
define_attribute_coercion( name, coerce ) click to toggle source
# File lib/shamu/attributes/assignment.rb, line 107
          def define_attribute_coercion( name, coerce ) # rubocop:disable Metrics/PerceivedComplexity
            coerce = cource_method( name, coerce )

            if coerce.is_a?( Class )
              define_method :"coerce_#{ name }" do |value|
                coerce.new( value ) if value
              end
            elsif !coerce || coerce.is_a?( Symbol )
              class_eval <<-RUBY, __FILE__, __LINE__ + 1
                def coerce_#{ name }( value )
                  value#{ coerce && ".#{ coerce }" }
                end
              RUBY
            elsif coerce
              define_method :"coerce_#{ name }", coerce
            end

            private :"coerce_#{ name }"
          end
define_attribute_reader( name, as: nil, ** ) click to toggle source
Calls superclass method
# File lib/shamu/attributes/assignment.rb, line 145
          def define_attribute_reader( name, as: nil, ** )
            super

            class_eval <<-RUBY, __FILE__, __LINE__ + 1
              def #{ name }_assigned?                # def attribute_assigned?
                assigned?( :#{ name } )              #   assigned( :attribute )
              end                                    # end
            RUBY
          end
define_attribute_writer( name, as: nil, ** ) click to toggle source
# File lib/shamu/attributes/assignment.rb, line 138
def define_attribute_writer( name, as: nil, ** )
  alias_method :"#{ name }=", :"assign_#{ name }"
  public :"#{ name }="

  alias_method :"#{ as }=", :"#{ name }=" if as
end