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 { |v| v.is_a?(Date) ? v : Time.at(v).to_date },
    time:     proc { |v| Time.at(v.to_f) },
    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]) }
}
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]) }
}

Instance Method Summary collapse

Instance Method Details

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



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

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



103
104
105
# File 'lib/dynamini/type_handler.rb', line 103

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

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



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

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



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

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



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

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

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



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/dynamini/type_handler.rb', line 28

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)


107
108
109
# File 'lib/dynamini/type_handler.rb', line 107

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

#handled_key(column, value) ⇒ Object



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

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)


99
100
101
# File 'lib/dynamini/type_handler.rb', line 99

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

#should_convert_elements?(handle, value) ⇒ Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/dynamini/type_handler.rb', line 95

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

#validate_handle(format, options) ⇒ Object



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

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