Module: Dynamini::TypeHandler

Included in:
Base
Defined in:
lib/dynamini/type_handler.rb

Constant Summary collapse

GETTER_PROCS =
{
  integer:  proc { |v| v.to_i },
  date:     proc do |v|
    if v.is_a?(Date)
      v
    else
      Time.methods.include?(:zone) ? Time.zone.at(v).to_date : Time.at(v).to_date
    end
  end,
  time:     proc do |v|
    Time.methods.include?(:zone) ? Time.zone.at(v.to_f) : Time.at(v.to_f)
  end,
  float:    proc { |v| v.to_f },
  symbol:   proc { |v| v.to_sym },
  string:   proc { |v| v.to_s },
  boolean:  proc { |v| v },
  array:    proc { |v| v.is_a?(Enumerable) ? v.to_a : [v] },
  set:      proc { |v| v.is_a?(Enumerable) ? Set.new(v) : Set.new([v]) }
}.freeze
SETTER_PROCS =
{
  integer:  proc { |v| v.to_i },
  time:     proc { |v| (v.is_a?(Date) ? v.to_time : v).to_f },
  float:    proc { |v| v.to_f },
  symbol:   proc { |v| v.to_s },
  string:   proc { |v| v.to_s },
  boolean:  proc { |v| v },
  date:     proc { |v| v.to_time.to_f },
  array:    proc { |v| v.is_a?(Enumerable) ? v.to_a : [v] },
  set:      proc { |v| v.is_a?(Enumerable) ? Set.new(v) : Set.new([v]) }
}.freeze

Instance Method Summary collapse

Instance Method Details

#attribute_callback(procs, handle, value, validate) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
# File 'lib/dynamini/type_handler.rb', line 93

def attribute_callback(procs, handle, value, validate)
  callback = procs[handle[:format]]
  if should_convert_elements?(handle, value)
    result = convert_elements(value, procs[handle[:options][:of]])
    callback.call(result)
  elsif validate && invalid_enumerable_value?(handle, value)
    raise ArgumentError, "Can't write a non-enumerable value to field handled as #{handle[:format]}"
  else
    callback.call(value)
  end
end

#convert_elements(enumerable, callback) ⇒ Object



113
114
115
# File 'lib/dynamini/type_handler.rb', line 113

def convert_elements(enumerable, callback)
  enumerable.map { |e| callback.call(e) }
end

#define_handled_getter(column, format_class, _options = {}) ⇒ Object



50
51
52
53
54
55
56
57
# File 'lib/dynamini/type_handler.rb', line 50

def define_handled_getter(column, format_class, _options = {})
  proc = GETTER_PROCS[format_class]
  fail 'Unsupported data type: ' + format_class.to_s if proc.nil?

  define_method(column) do
    read_attribute(column)
  end
end

#define_handled_setter(column, format_class) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/dynamini/type_handler.rb', line 59

def define_handled_setter(column, format_class)
  method_name = (column.to_s + '=')
  proc = SETTER_PROCS[format_class]
  fail 'Unsupported data type: ' + format_class.to_s if proc.nil?
  define_method(method_name) do |value|
    write_attribute(column, value)
  end
end

#format_default(format_class) ⇒ Object



68
69
70
71
72
73
74
75
# File 'lib/dynamini/type_handler.rb', line 68

def format_default(format_class)
  case format_class
    when :array
      []
    when :set
      Set.new
  end
end

#handle(column, format_class, options = {}) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/dynamini/type_handler.rb', line 38

def handle(column, format_class, options = {})
  validate_handle(format_class, options)

  options[:default] ||= format_default(format_class)
  options[:default] ||= Set.new if format_class == :set

  self.handles = self.handles.merge(column => { format: format_class, options: options })

  define_handled_getter(column, format_class, options)
  define_handled_setter(column, format_class)
end

#handled_as?(handle, type) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/dynamini/type_handler.rb', line 117

def handled_as?(handle, type)
  type.include? handle[:format]
end

#handled_key(column, value) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/dynamini/type_handler.rb', line 85

def handled_key(column, value)
  if handles[column]
    attribute_callback(GETTER_PROCS, handles[column], value, false)
  else
    value
  end
end

#invalid_enumerable_value?(handle, value) ⇒ Boolean

Returns:

  • (Boolean)


109
110
111
# File 'lib/dynamini/type_handler.rb', line 109

def invalid_enumerable_value?(handle, value)
  handled_as?(handle, [:array, :set]) && !value.is_a?(Enumerable)
end

#should_convert_elements?(handle, value) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/dynamini/type_handler.rb', line 105

def should_convert_elements?(handle, value)
  handle[:options][:of] && (value.is_a?(Array) || value.is_a?(Set))
end

#validate_handle(format, options) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/dynamini/type_handler.rb', line 77

def validate_handle(format, options)
  if format == :set
    if options[:of] && [:set, :array].include?(options[:of])
      raise ArgumentError, 'Invalid handle: cannot store non-primitive datatypes within a set.'
    end
  end
end