module Cassie::Statements::Statement::Mapping::ClassMethods

@!parse extend ClassMethods

Public Instance Methods

map_from(resource_name) click to toggle source

DSL setting a getter and setter.

When use with a relation (where) or assignment (set), the fetching of column values are delegated to the object in this getter.

@note This delegation behavor gets last preference.

* An overwritten +column_name+ getter has first preference
* the +@column_name+ instance variable has next preference
* the mapped resource delegation has last preference

@example Simple Mapping delegation

Class Statement
  include Cassie::Statements::Statement:Relations
  include Cassie::Statements::Statement:Mapping

  where :name

  map_from :user
end

s = Statement.new
s.user = User.new(id: 1)
s.id
#=> 1
# File lib/cassie/statements/statement/mapping.rb, line 41
def map_from(resource_name)
  define_method resource_name do
    _resource
  end

  define_method "#{resource_name}=" do |val|
    self._resource = val
  end
end

Protected Instance Methods

define_argument_accessor(name) click to toggle source

override definition of getter and setter methods to look up argument values from resource object

# File lib/cassie/statements/statement/mapping.rb, line 56
def define_argument_accessor(name)
  unless Symbol === name
    raise ArgumentError, "A Symbol is required for the accessor methods for setting/getting a relation's value. #{name.class} (#{name}) given."
  end

  getter = name
  setter = "#{name}="

  if method_defined?(getter) || method_defined?(setter)
    raise "accessor or getter already defined for #{name}. Fix the collisions by using the `:value` option."
  else
    # Order of prefrence for finding term value
    #  1. overwritten getter instance method
    #    def id
    #      "some constant"
    #    end
    #  2. value set by setter instance method
    #    def ensure_special_is_special
    #      @id = "one off value" if special?
    #    end
    #  3. getter instance method on resource object
    #    query.user = User.new(id: 105)
    #    query.id
    #    => 105
    define_method getter do
      # 1 is handled by overwritten definition

      # 2: prefer instance value
      if instance_variable_defined?("@#{name}")
        return instance_variable_get("@#{name}")
      end

      # 3: fetch from resource
      if _resource && _resource.respond_to?(name)
        _resource.send(name)
      end
    end

    # query.id = 'some val'
    # initialize underlying instance var
    # which is preferred over resource object attribute
    #
    # Issue: if client defines value for attribute
    # they might assume later setting to nil would
    # revert to behavior of fetching from resource object attribute
    # but that is not the case since the variable is defined
    # and we can't know they didn't want the value of 'nil' to be used
    attr_writer name
  end
end