Module: Modis::Attribute::ClassMethods

Defined in:
lib/modis/attribute.rb

Instance Method Summary collapse

Instance Method Details

#attribute(name, type, options = {}) ⇒ Object

Raises:



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
72
# File 'lib/modis/attribute.rb', line 34

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 = <<-RUBY
  if value && !(#{predicate})
    raise Modis::AttributeCoercionError, "Received value of type '\#{value.class}', expected '#{type_classes.join("', '")}' for attribute '#{name}'."
  end
  RUBY

  class_eval <<-RUBY, __FILE__, __LINE__
    def #{name}
      attributes['#{name}']
    end

    def #{name}=(value)
      #{value_coercion}

      # ActiveSupport's Time#<=> does not perform well when comparing with NilClass.
      if (value.nil? ^ attributes['#{name}'].nil?) || (value != attributes['#{name}'])
        #{type_check}
        #{name}_will_change!
        attributes['#{name}'] = value
      end
    end
  RUBY
end

#bootstrap_attributes(parent = nil) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/modis/attribute.rb', line 21

def bootstrap_attributes(parent = nil)
  attr_reader :attributes

  class << self
    attr_accessor :attributes, :attributes_with_defaults
  end

  self.attributes = parent ? parent.attributes.dup : {}
  self.attributes_with_defaults = parent ? parent.attributes_with_defaults.dup : {}

  attribute :id, :integer unless parent
end