Class: Model

Inherits:
Object show all
Includes:
ModelWrapper, ObjectTracking, ReactiveTags
Defined in:
lib/volt/models/model.rb

Direct Known Subclasses

Params

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ObjectTracking

#__setup_tracking

Methods included from ModelWrapper

#wrap_value, #wrap_values

Methods included from ReactiveTags

included, #reactive_method_tag

Constructor Details

#initialize(attributes = {}, parent = nil, path = nil, class_paths = nil) ⇒ Model

Returns a new instance of Model.



35
36
37
38
39
# File 'lib/volt/models/model.rb', line 35

def initialize(attributes={}, parent=nil, path=nil, class_paths=nil)
  self.attributes = wrap_values(attributes)
  @parent = parent
  @path = path
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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



68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/volt/models/model.rb', line 68

def method_missing(method_name, *args, &block)
  if method_name[0] == '_'
    if method_name[-1] == '='
      # Assigning an attribute with =
      assign_attribute(method_name, *args, &block)
    else
      read_attribute(method_name)
    end
  else
    # Call method directly on attributes.  (since they are
    # not using _ )
    attributes.send(method_name, *args, &block)
  end
end

Instance Attribute Details

#attributesObject

Returns the value of attribute attributes.



20
21
22
# File 'lib/volt/models/model.rb', line 20

def attributes
  @attributes
end

#parentObject (readonly)

Returns the value of attribute parent.



21
22
23
# File 'lib/volt/models/model.rb', line 21

def parent
  @parent
end

#pathObject (readonly)

Returns the value of attribute path.



21
22
23
# File 'lib/volt/models/model.rb', line 21

def path
  @path
end

Instance Method Details

#!Object

Pass through needed



47
48
49
# File 'lib/volt/models/model.rb', line 47

def !
  !attributes
end

#<<(value) ⇒ Object

Initialize an empty array and append to it



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/volt/models/model.rb', line 165

def <<(value)
  @parent.expand!
  result = @parent.send(@path)
  
  if result.nil?
    # If this isn't a model yet, instantiate it
    @parent.send(:"#{@path}=", ArrayModel.new([], @parent, @path))
    result = @parent.send(@path)
    
    # Add the new item
    result << value
  end
  
  return result
end

#==(val) ⇒ Object

Pass the comparison through



42
43
44
# File 'lib/volt/models/model.rb', line 42

def ==(val)
  attributes == val
end

#assign_attribute(method_name, *args, &block) ⇒ Object

Do the assignment to a model and trigger a changed event



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/volt/models/model.rb', line 84

def assign_attribute(method_name, *args, &block)
  self.expand!
  # Assign, without the =
  attribute_name = method_name[0..-2].to_sym
  
  value = args[0]
  __assign_element(attribute_name, value)
  
  attributes[attribute_name] = wrap_value(value)
  trigger_by_attribute!('changed', attribute_name)
end

#delete(*args) ⇒ Object



54
55
56
57
58
# File 'lib/volt/models/model.rb', line 54

def delete(*args)
  __clear_element(args[0])
  attributes.delete(*args)
  trigger_by_attribute!('changed', args[0])
end

#expand!Object

If this model is nil, it makes it into a hash model, then sets it up to track from the parent.



149
150
151
152
153
154
155
156
157
158
# File 'lib/volt/models/model.rb', line 149

def expand!
  if attributes.nil?
    self.attributes = {}
    if @parent
      @parent.expand!
    
      @parent.attributes[@path] = self
    end
  end
end

#false?Boolean

Returns:



27
28
29
# File 'lib/volt/models/model.rb', line 27

def false?
  attributes.false?
end

#inspectObject



181
182
183
# File 'lib/volt/models/model.rb', line 181

def inspect
  "<#{self.class.to_s}:#{@path} #{attributes.inspect}>"
end

#new_model(*args) ⇒ Object



130
131
132
# File 'lib/volt/models/model.rb', line 130

def new_model(*args)
  Model.new(*args)
end

#nil?Boolean

Returns:



23
24
25
# File 'lib/volt/models/model.rb', line 23

def nil?
  attributes.nil?
end

#read_attribute(method_name) ⇒ Object

When reading an attribute, we need to handle reading on: 1) a nil model, which returns a wrapped error 2) reading directly from attributes 3) trying to read a key that doesn’t exist.



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/volt/models/model.rb', line 100

def read_attribute(method_name)
  # Reading an attribute, we may get back a nil model.
  method_name = method_name.to_sym
  
  if attributes == nil
    # The method we are calling is on a nil model, return a wrapped 
    # exception.
    return return_undefined_method(method_name)
  elsif attributes && attributes.has_key?(method_name)
    # Method has the key, look it up directly
    return attributes[method_name]
  else
    return new_model(nil, self, method_name)
  end
end

#return_undefined_method(method_name) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/volt/models/model.rb', line 116

def return_undefined_method(method_name)
  # Methods called on nil capture an error so the user can know where
  # their nil calls are.  This error can be re-raised at a later point.
  begin
    raise NilMethodCall.new("undefined method `#{method_name}' for #{self.to_s}")
  rescue => e
    result = e

    # Cleanup backtrace around ReactiveValue's
    # TODO: this could be better
    result.backtrace.reject! {|line| line['lib/models/model.rb'] || line['lib/models/live_value.rb'] }
  end
end

#trigger_by_attribute!(event_name, attribute, *passed_args) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/volt/models/model.rb', line 134

def trigger_by_attribute!(event_name, attribute, *passed_args)
  trigger_by_scope!(event_name, *passed_args) do |scope|
    method_name, *args, block = scope
    
    # TODO: Opal bug
    args ||= []
    
    # Any methods without _ are not directly related to one attribute, so
    # they should all trigger
    !method_name || method_name[0] != '_' || (method_name == attribute.to_sym && args.size == 0)
  end
end

#true?Boolean

Returns:



31
32
33
# File 'lib/volt/models/model.rb', line 31

def true?
  attributes.true?
end