module DataSteroid::Properties

Define behaviour to properties of entity.

Public Instance Methods

add_property(name, *args) click to toggle source

Type might be defined like this:

property :time_field, Time, default: -> { Time.now }

or like this:

property :time_field, type: Time, default: -> { Time.now }
# File lib/data_steroid/properties.rb, line 109
def add_property(name, *args)
  options = args[-1].is_a?(Hash) ? args[-1].slice(:default, :type) : {}
  options[:type] = args[0] if args[0] && !(args[0].is_a?(Hash) && args[0].key?(:default))
  properties[name.to_s] = options
  create_accessors(name, options)
  self
end
coerce(value, type) click to toggle source
# File lib/data_steroid/properties.rb, line 49
def coerce(value, type)
  if value.nil? || !type
    value
  else
    case
    when Array == type || Array === type then coerce_array(value, type)
    when Hash  == type || Hash  === type then coerce_hash(value, type)
    when type == Time  then coerce_time(value)
    else coerce_other(value, type)
    end
  end
end
coerce_array(value, type) click to toggle source
# File lib/data_steroid/properties.rb, line 62
def coerce_array(value, type)
  # type: generic Array
  if type == Array
    coerce_other(value, type)
  # type: Array[Something]
  elsif value.respond_to?(:map)
    value.map do |element|
      coerce(element, type[0])
    end
  else
    raise ArgumentError.new "Invalid coercion: #{value.class} => #{type}"
  end
end
coerce_hash(value, type) click to toggle source
# File lib/data_steroid/properties.rb, line 76
def coerce_hash(value, type)
  # type: generic Hash
  if type == Hash
    coerce_other(value, type)
  # type: Hash[Something => Other thing]
  elsif value.respond_to?(:to_h)
    k_type, v_type = type.to_a[0]
    value.to_h.map{ |k,v| [ coerce(k, k_type), coerce(v, v_type) ] }.to_h
  else
    raise ArgumentError.new "Invalid coercion: #{value.class} => #{type}"
  end
end
coerce_other(value, type) click to toggle source
# File lib/data_steroid/properties.rb, line 97
def coerce_other(value, type)
  coercer[value.class].send("to_#{type.to_s.downcase}", value)
end
coerce_time(value) click to toggle source
# File lib/data_steroid/properties.rb, line 89
def coerce_time(value)
  case value
  when Integer then Time.at(value)
  when String then Time.parse(value)
  else value
  end
end
coercer() click to toggle source
# File lib/data_steroid/properties.rb, line 45
def coercer
  @coercer ||= Coercible::Coercer.new
end
create_accessors(name, options) click to toggle source

www.leighhalliday.com/ruby-metaprogramming-creating-methods

# File lib/data_steroid/properties.rb, line 118
def create_accessors(name, options)
  define_method(name) do # Define get method
    instance_variable_get("@#{name}")
  end

  define_method("#{name}=") do |value| # Define set method
    instance_variable_set("@#{name}", coerce(value, options[:type]))
  end
end
properties=(properties) click to toggle source
# File lib/data_steroid/properties.rb, line 19
def properties=(properties)
  if properties.is_a? ::Hash
    properties.each_pair { |key, value| send("#{key}=", value) }
  else
    raise Datastore::Errors::DatastoreError.new 'Properties params must be a Hash'
  end
rescue
  raise Datastore::Errors::DatastoreError.new 'Property invalid'
end
properties_names() click to toggle source
# File lib/data_steroid/properties.rb, line 29
def properties_names
  properties.keys
end
set_default_values() click to toggle source
# File lib/data_steroid/properties.rb, line 35
def set_default_values
  properties.each_pair do |name, options|
    next unless options.key? :default
    default = options[:default]
    # Default might be a lambda
    value = default.respond_to?(:call) ? default.call : default
    send("#{name}=", value)
  end
end