32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
# File 'lib/modis/attribute.rb', line 32
def attribute(name, type, options = {})
name = name.to_s
raise AttributeError, "Attribute with name '#{name}' has already been specified." if attributes.key?(name)
type_classes = Array(type).map do |t|
raise UnsupportedAttributeType, t unless TYPES.key?(t)
TYPES[t]
end.flatten
attributes[name] = options.update(type: type)
attributes_with_defaults[name] = options[:default]
define_attribute_methods([name])
value_coercion = type == :timestamp ? 'value = Time.new(*value) if value && value.is_a?(Array) && value.count == 7' : nil
predicate = type_classes.map { |cls| "value.is_a?(#{cls.name})" }.join(' || ')
type_check = " if value && !(\#{predicate})\n raise Modis::AttributeCoercionError, \"Received value of type '\\\#{value.class}', expected '\#{type_classes.join(\"', '\")}' for attribute '\#{name}'.\"\n end\n RUBY\n\n class_eval <<-RUBY, __FILE__, __LINE__ + 1\n def \#{name}\n attributes['\#{name}']\n end\n\n def \#{name}=(value)\n \#{value_coercion}\n\n # ActiveSupport's Time#<=> does not perform well when comparing with NilClass.\n if (value.nil? ^ attributes['\#{name}'].nil?) || (value != attributes['\#{name}'])\n \#{type_check}\n \#{name}_will_change!\n attributes['\#{name}'] = value\n end\n end\n RUBY\nend\n"
|