Class: Volt::ArrayModel

Inherits:
ReactiveArray show all
Includes:
ModelWrapper, Models::Helpers::ArrayModel, Models::Helpers::Base, StateManager
Defined in:
lib/volt/models/array_model.rb

Direct Known Subclasses

Cursor

Constant Summary

Constants included from Models::Helpers::Base

Models::Helpers::Base::ID_CHARS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Models::Helpers::ArrayModel

#loaded?, #loaded_state

Methods included from StateManager

#change_state_to

Methods included from Models::Helpers::Base

#deep_unwrap, #event_added, #event_removed, #generate_id, included, #root, #self_attributes, #setup_persistor, #store

Methods included from ModelWrapper

#wrap_value, #wrap_values

Methods inherited from ReactiveArray

#==, #[], #[]=, #all?, #any?, #clear, #count, #delete_at, #each, #empty?, #insert, #method_missing, #size

Methods included from Eventable

#on, #remove_listener, #trigger!

Constructor Details

#initialize(array = [], options = {}) ⇒ ArrayModel

Returns a new instance of ArrayModel.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/volt/models/array_model.rb', line 60

def initialize(array = [], options = {})
  @options   = options
  @parent    = options[:parent]
  @path      = options[:path] || []
  @persistor = setup_persistor(options[:persistor])

  array = wrap_values(array)

  super(array)

  if @persistor
    @persistor.loaded
  else
    change_state_to(:loaded_state, :loaded, false)
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Volt::ReactiveArray

Instance Attribute Details

#arrayObject (readonly)

Returns the value of attribute array.



17
18
19
# File 'lib/volt/models/array_model.rb', line 17

def array
  @array
end

#optionsObject (readonly)

Returns the value of attribute options.



17
18
19
# File 'lib/volt/models/array_model.rb', line 17

def options
  @options
end

#parentObject (readonly)

Returns the value of attribute parent.



17
18
19
# File 'lib/volt/models/array_model.rb', line 17

def parent
  @parent
end

#pathObject (readonly)

Returns the value of attribute path.



17
18
19
# File 'lib/volt/models/array_model.rb', line 17

def path
  @path
end

#persistorObject (readonly)

Returns the value of attribute persistor.



17
18
19
# File 'lib/volt/models/array_model.rb', line 17

def persistor
  @persistor
end

Class Method Details

.process_class_name(name) ⇒ Object



252
253
254
# File 'lib/volt/models/array_model.rb', line 252

def self.process_class_name(name)
  name.pluralize
end

.proxy_to_persistor(*method_names) ⇒ Object

Some methods get passed down to the persistor.



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/volt/models/array_model.rb', line 46

def self.proxy_to_persistor(*method_names)
  method_names.each do |method_name|
    define_method(method_name) do |*args, &block|
      if @persistor.respond_to?(method_name)
        @persistor.send(method_name, *args, &block)
      else
        fail "this model's persistance layer does not support #{method_name}, try using store"
      end
    end
  end
end

.proxy_with_load(*method_names) ⇒ Object

For many methods, we want to register a dependency on the root_dep as soon as the method is called, so it can begin loading. Also, some persistors need to have special loading logic (such as returning a promise instead of immediately returning). To accomplish this, we call the #run_once_loaded method on the persistor.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/volt/models/array_model.rb', line 24

def self.proxy_with_load(*method_names)
  method_names.each do |method_name|
    old_method_name = :"__old_#{method_name}"
    alias_method(old_method_name, method_name)

    define_method(method_name) do |*args, &block|
      # track on the root dep
      persistor.try(:root_dep).try(:depend)

      if persistor.respond_to?(:run_once_loaded) &&
          !Volt.in_mode?(:no_model_promises)
        persistor.run_once_loaded(block) do
          send(old_method_name, *args)
        end
      else
        send(old_method_name, *args)
      end
    end
  end
end

Instance Method Details

#+(*args) ⇒ Object

Make sure it gets wrapped



183
184
185
186
# File 'lib/volt/models/array_model.rb', line 183

def +(*args)
  args = wrap_values(args)
  super(*args)
end

#<<(model) ⇒ Object

Make sure it gets wrapped



89
90
91
# File 'lib/volt/models/array_model.rb', line 89

def <<(model)
  create_new_model(model, :<<)
end

#allObject

Return the model, on store, .all is proxied to wait for load and return a promise.



166
167
168
# File 'lib/volt/models/array_model.rb', line 166

def all
  self
end

#append(model) ⇒ Object

Works like << except it always returns a promise



96
97
98
# File 'lib/volt/models/array_model.rb', line 96

def append(model)
  create_new_model(model, :append)
end

#attributesObject



77
78
79
# File 'lib/volt/models/array_model.rb', line 77

def attributes
  self
end

#buffer(attrs = {}) ⇒ Object



231
232
233
234
235
236
237
238
239
# File 'lib/volt/models/array_model.rb', line 231

def buffer(attrs = {})
  model_path  = options[:path] + [:[]]
  model_klass = Volt::Model.class_at_path(model_path)

  new_options = options.merge(path: model_path, save_to: self, buffer: true).reject { |k, _| k.to_sym == :persistor }
  model       = model_klass.new(attrs, new_options)

  model
end

#create(model = {}) ⇒ Object

Create does append with a default empty model



101
102
103
# File 'lib/volt/models/array_model.rb', line 101

def create(model={})
  create_new_model(model, :create)
end

#delete(val) ⇒ Object



106
107
108
109
110
111
112
113
114
# File 'lib/volt/models/array_model.rb', line 106

def delete(val)
  # Check to make sure the models are allowed to be deleted
  if !val.is_a?(Model) || val.can_delete?
    result = super
    Promise.new.resolve(result)
  else
    Promise.new.reject("permissions did not allow delete for #{val.inspect}.")
  end
end

#fail_not_found_if_nil(promise) ⇒ Object

Raise a RecordNotFoundException if the promise returns a nil.



242
243
244
245
246
247
248
249
250
# File 'lib/volt/models/array_model.rb', line 242

def fail_not_found_if_nil(promise)
  promise.then do |val|
    if val
      val
    else
      raise RecordNotFoundException.new
    end
  end
end

#fetch_first(&block) ⇒ Object

returns a promise to fetch the first instance



171
172
173
174
# File 'lib/volt/models/array_model.rb', line 171

def fetch_first(&block)
  Volt.logger.warn('.fetch_first is deprecated in favor of .first')
  first
end

#firstObject



116
117
118
119
120
121
122
# File 'lib/volt/models/array_model.rb', line 116

def first
  if persistor.is_a?(Persistors::ArrayStore)
    limit(1)[0]
  else
    self[0]
  end
end

#first!Object

Same as first, except it returns a promise (even on page collection), and it fails with a RecordNotFoundException if no result is found.



126
127
128
# File 'lib/volt/models/array_model.rb', line 126

def first!
  fail_not_found_if_nil(first)
end

#first_or_createObject

Return the first item in the collection, or create one if one does not exist yet.



132
133
134
135
136
137
138
139
140
# File 'lib/volt/models/array_model.rb', line 132

def first_or_create
  first.then do |item|
    if item
      item
    else
      create
    end
  end
end

#inject(*args) ⇒ Object

Make sure it gets wrapped



177
178
179
180
# File 'lib/volt/models/array_model.rb', line 177

def inject(*args)
  args = wrap_values(args)
  super(*args)
end

#inspectObject



219
220
221
222
223
224
225
226
227
228
229
# File 'lib/volt/models/array_model.rb', line 219

def inspect
  # Track on size
  @size_dep.depend
  str = "#<#{self.class}"
  # str += " state:#{loaded_state}"
  # str += " path:#{path.join('.')}" if path
  # str += " persistor:#{persistor.inspect}" if persistor
  str += " #{@array.inspect}>"

  str
end

#lastObject



142
143
144
# File 'lib/volt/models/array_model.rb', line 142

def last
  self[-1]
end

#new_array_model(*args) ⇒ Object



192
193
194
# File 'lib/volt/models/array_model.rb', line 192

def new_array_model(*args)
  Volt::ArrayModel.class_at_path(options[:path]).new(*args)
end

#new_model(*args) ⇒ Object



188
189
190
# File 'lib/volt/models/array_model.rb', line 188

def new_model(*args)
  Volt::Model.class_at_path(options[:path]).new(*args)
end

#reactive_array_appendObject

Alias append for use inside of child append



94
# File 'lib/volt/models/array_model.rb', line 94

alias_method :reactive_array_append, :append

#reverseObject



146
147
148
149
# File 'lib/volt/models/array_model.rb', line 146

def reverse
  @size_dep.depend
  @array.reverse
end

#selectObject

Array#select, with reactive notification



152
153
154
155
156
157
158
159
160
161
162
# File 'lib/volt/models/array_model.rb', line 152

def select
  new_array = []
  @array.size.times do |index|
    value = @array[index]
    if yield(value)
      new_array << value
    end
  end

  new_array
end

#state_for(*args) ⇒ Object



81
82
83
84
85
86
# File 'lib/volt/models/array_model.rb', line 81

def state_for(*args)
  # Track on root dep
  persistor.try(:root_dep).try(:depend)

  super
end

#to_aObject

Convert the model to an array all of the way down



197
198
199
200
201
202
203
204
205
206
# File 'lib/volt/models/array_model.rb', line 197

def to_a
  @size_dep.depend
  array = []
  Volt.run_in_mode(:no_model_promises) do
    attributes.size.times do |index|
      array << deep_unwrap(self[index])
    end
  end
  array
end

#to_jsonObject



208
209
210
211
212
213
214
215
216
# File 'lib/volt/models/array_model.rb', line 208

def to_json
  array = to_a

  if array.is_a?(Promise)
    array.then(&:to_json)
  else
    array.to_json
  end
end