Class: Volt::ArrayModel
- Inherits:
-
ReactiveArray
- Object
- ReactiveArray
- Volt::ArrayModel
- Includes:
- ModelHelpers, ModelWrapper, StateHelpers, StateManager
- Defined in:
- lib/volt/models/array_model.rb
Direct Known Subclasses
Constant Summary
Constants included from ModelHelpers
Instance Attribute Summary collapse
-
#array ⇒ Object
readonly
Returns the value of attribute array.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#persistor ⇒ Object
readonly
Returns the value of attribute persistor.
Class Method Summary collapse
-
.proxy_to_persistor(*method_names) ⇒ Object
Some methods get passed down to the persistor.
-
.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.
Instance Method Summary collapse
-
#+(*args) ⇒ Object
Make sure it gets wrapped.
-
#<<(model) ⇒ Object
Make sure it gets wrapped.
-
#all ⇒ Object
Return the model, on store, .all is proxied to wait for load and return a promise.
-
#append(model) ⇒ Object
Works like << except it always returns a promise.
- #attributes ⇒ Object
- #buffer(attrs = {}) ⇒ Object
-
#create(model = {}) ⇒ Object
Create does append with a default empty model.
- #delete(val) ⇒ Object
-
#fail_not_found_if_nil(promise) ⇒ Object
Raise a RecordNotFoundException if the promise returns a nil.
-
#fetch_first(&block) ⇒ Object
returns a promise to fetch the first instance.
- #first ⇒ Object
-
#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.
-
#first_or_create ⇒ Object
Return the first item in the collection, or create one if one does not exist yet.
-
#initialize(array = [], options = {}) ⇒ ArrayModel
constructor
A new instance of ArrayModel.
-
#inject(*args) ⇒ Object
Make sure it gets wrapped.
- #inspect ⇒ Object
- #last ⇒ Object
- #new_array_model(*args) ⇒ Object
- #new_model(*args) ⇒ Object
- #reverse ⇒ Object
-
#select ⇒ Object
Array#select, with reactive notification.
- #state_for(*args) ⇒ Object
-
#to_a ⇒ Object
Convert the model to an array all of the way down.
- #to_json ⇒ Object
Methods included from StateHelpers
Methods included from StateManager
Methods included from ModelHelpers
#deep_unwrap, #event_added, #event_removed, #generate_id, included, #self_attributes, #setup_persistor
Methods included from ModelWrapper
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
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 = @parent = [:parent] @path = [:path] || [] @persistor = setup_persistor([: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
#array ⇒ Object (readonly)
Returns the value of attribute array.
17 18 19 |
# File 'lib/volt/models/array_model.rb', line 17 def array @array end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
17 18 19 |
# File 'lib/volt/models/array_model.rb', line 17 def @options end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
17 18 19 |
# File 'lib/volt/models/array_model.rb', line 17 def parent @parent end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
17 18 19 |
# File 'lib/volt/models/array_model.rb', line 17 def path @path end |
#persistor ⇒ Object (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
.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
239 240 241 242 |
# File 'lib/volt/models/array_model.rb', line 239 def +(*args) args = wrap_values(args) super(*args) end |
#<<(model) ⇒ Object
Make sure it gets wrapped
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/volt/models/array_model.rb', line 89 def <<(model) if model.is_a?(Model) # Set the new path and the persistor. model. = @options.merge(path: @options[:path] + [:[]]) else model = wrap_values([model]).first end if model.is_a?(Model) && !model.can_create? fail "permissions did not allow create for #{model.inspect}" end # Add it to the array and trigger any watches or on events. super(model) if @persistor promise = @persistor.added(model, @array.size - 1) if promise && promise.is_a?(Promise) return promise.then do # Mark the model as not new model.instance_variable_set('@new', false) # Mark the model as loaded model.change_state_to(:loaded_state, :loaded) # return the model model end.fail do |err| # remove from the collection because it failed to save on the server # we don't need to call delete on the server. index = @array.index(model) delete_at(index, true) # re-raise, err might not be an Error object, so we use a rejected promise to re-raise Promise.new.reject(err) end end end # Return this model Promise.new.resolve(model) end |
#all ⇒ Object
Return the model, on store, .all is proxied to wait for load and return a promise.
206 207 208 |
# File 'lib/volt/models/array_model.rb', line 206 def all self end |
#append(model) ⇒ Object
Works like << except it always returns a promise
134 135 136 137 138 139 |
# File 'lib/volt/models/array_model.rb', line 134 def append(model) # Wrap results in a promise Promise.new.resolve(nil).then do send(:<<, model) end end |
#attributes ⇒ Object
77 78 79 |
# File 'lib/volt/models/array_model.rb', line 77 def attributes self end |
#buffer(attrs = {}) ⇒ Object
289 290 291 292 293 294 295 296 297 |
# File 'lib/volt/models/array_model.rb', line 289 def buffer(attrs = {}) model_path = [:path] + [:[]] model_klass = Volt::Model.class_at_path(model_path) = .merge(path: model_path, save_to: self, buffer: true).reject { |k, _| k.to_sym == :persistor } model = model_klass.new(attrs, ) model end |
#create(model = {}) ⇒ Object
Create does append with a default empty model
142 143 144 |
# File 'lib/volt/models/array_model.rb', line 142 def create(model={}) append(model) end |
#delete(val) ⇒ Object
146 147 148 149 150 151 152 153 154 |
# File 'lib/volt/models/array_model.rb', line 146 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.
300 301 302 303 304 305 306 307 308 |
# File 'lib/volt/models/array_model.rb', line 300 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
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/volt/models/array_model.rb', line 211 def fetch_first(&block) persistor = self.persistor if persistor && persistor.is_a?(Persistors::ArrayStore) # On array store, we wait for the result to be loaded in. promise = limit(1).fetch do |res| result = res.first result end else # On all other persistors, it should be loaded already promise = Promise.new.resolve(first) end # Run any passed in blocks after fetch promise = promise.then(&block) if block promise end |
#first ⇒ Object
156 157 158 159 160 161 162 |
# File 'lib/volt/models/array_model.rb', line 156 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.
166 167 168 |
# File 'lib/volt/models/array_model.rb', line 166 def first! fail_not_found_if_nil(first) end |
#first_or_create ⇒ Object
Return the first item in the collection, or create one if one does not exist yet.
172 173 174 175 176 177 178 179 180 |
# File 'lib/volt/models/array_model.rb', line 172 def first_or_create first.then do |item| if item item else create end end end |
#inject(*args) ⇒ Object
Make sure it gets wrapped
233 234 235 236 |
# File 'lib/volt/models/array_model.rb', line 233 def inject(*args) args = wrap_values(args) super(*args) end |
#inspect ⇒ Object
275 276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/volt/models/array_model.rb', line 275 def inspect Computation.run_without_tracking do # 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 end |
#last ⇒ Object
182 183 184 |
# File 'lib/volt/models/array_model.rb', line 182 def last self[-1] end |
#new_array_model(*args) ⇒ Object
248 249 250 |
# File 'lib/volt/models/array_model.rb', line 248 def new_array_model(*args) ArrayModel.new(*args) end |
#new_model(*args) ⇒ Object
244 245 246 |
# File 'lib/volt/models/array_model.rb', line 244 def new_model(*args) Volt::Model.class_at_path([:path]).new(*args) end |
#reverse ⇒ Object
186 187 188 189 |
# File 'lib/volt/models/array_model.rb', line 186 def reverse @size_dep.depend @array.reverse end |
#select ⇒ Object
Array#select, with reactive notification
192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/volt/models/array_model.rb', line 192 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_a ⇒ Object
Convert the model to an array all of the way down
253 254 255 256 257 258 259 260 261 262 |
# File 'lib/volt/models/array_model.rb', line 253 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 |