Class: Lego::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/lego/model.rb

Defined Under Namespace

Classes: ParseError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ Model

Returns a new instance of Model.



105
106
107
# File 'lib/lego/model.rb', line 105

def initialize(attrs={})
  @attributes = attrs.freeze
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



115
116
117
# File 'lib/lego/model.rb', line 115

def method_missing(name, *args, &block)
  attributes.fetch(name.to_sym) { super }
end

Instance Attribute Details

#attributesObject (readonly)

Returns the value of attribute attributes.



109
110
111
# File 'lib/lego/model.rb', line 109

def attributes
  @attributes
end

Class Method Details

._parse(data) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/lego/model.rb', line 83

def _parse(data)
  data = data.dup

  attrs = {}

  parsers.each do |name, parser|
    name = name.to_sym
    value = data.key?(name) ? data.delete(name) : data.delete(name.to_s)

    attrs[name] = parser.parse(value)
  end

  fail ArgumentError, "Unknown attributes: #{data}" unless data.empty?

  if attrs.all?{ |k,v| v.value? }
    Lego.just(Hash[*attrs.map{ |k,v| [k, v.value] }.flatten(1)])
  else
    Lego.fail(Hash[*attrs.map{ |k,v| [k, v.error] if v.error? }.compact.flatten(1)])
  end
end

._validate(obj) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/lego/model.rb', line 63

def _validate(obj)
  attrs = {}
  validations.each do |name, attr_validations|
    attrs[name] = Lego.just(obj)
    attr_validations.each do |validation|
      if validation.is_a?(Symbol)
        callable_method_name = validation.to_sym
        validation = ->(o){ o.method(callable_method_name).call }
      end
      attrs[name] = attrs[name].next(validation)
    end
  end

  if attrs.all?{ |k,v| v.value? }
    Lego.just(obj)
  else
    Lego.fail(Hash[*attrs.map{ |k,v| [k, v.error] if v.error? }.compact.flatten(1)])
  end
end

.attribute(attr, type, *args) ⇒ Object



18
19
20
# File 'lib/lego/model.rb', line 18

def attribute(attr, type, *args)
  parsers[attr.to_sym] = Lego.value_parser(type, *args)
end

.attribute_namesObject



30
31
32
# File 'lib/lego/model.rb', line 30

def attribute_names
  parsers.keys
end

.coerce(hash) ⇒ Object



43
44
45
46
# File 'lib/lego/model.rb', line 43

def coerce(hash)
  res = parse(hash)
  res.value? ? res.value : fail(ParseError.new(res.error))
end

.parse(hash) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/lego/model.rb', line 48

def parse(hash)
  return Lego.just(hash) if hash.instance_of?(self)

  fail ArgumentError, "attrs must be hash: '#{hash.inspect}'" unless hash.respond_to?(:key?)

  result = _parse(hash)

  if result.value?
    model = new(result.value)
    _validate(model)
  else
    result
  end
end

.parsersObject



22
23
24
# File 'lib/lego/model.rb', line 22

def parsers
  @_parsers ||= {}
end

.validates(attr, callable = nil, &block) ⇒ Object



34
35
36
37
38
39
40
41
# File 'lib/lego/model.rb', line 34

def validates(attr, callable=nil, &block)
  attr = attr.to_sym
  if callable && callable.is_a?(Symbol)
    validations[attr] << callable
  else
    validations[attr] << block
  end
end

.validationsObject



26
27
28
# File 'lib/lego/model.rb', line 26

def validations
  @_validations ||= Hash.new { |h,k| h[k] = [] }
end

Instance Method Details

#==(o) ⇒ Object Also known as: eql?

Equality



121
122
123
# File 'lib/lego/model.rb', line 121

def ==(o)
  o.class == self.class && o.attributes == attributes
end

#as_json(opts = {}) ⇒ Object

Serialize

Raises:

  • (NotImplementedError)


132
133
134
135
136
137
138
139
# File 'lib/lego/model.rb', line 132

def as_json(opts={})
  raise NotImplementedError, 'as_json with arguments' unless opts.empty?
  {}.tap do |h|
    attributes.each do |attr, val|
      h[attr] = val.as_json
    end
  end
end

#hashObject



126
127
128
# File 'lib/lego/model.rb', line 126

def hash
  attributes.hash
end

#merge(other) ⇒ Object



111
112
113
# File 'lib/lego/model.rb', line 111

def merge(other)
  self.class.coerce(as_json.deep_merge(other))
end