Class: RMXFirebaseCollection
- Inherits:
-
Object
- Object
- RMXFirebaseCollection
- Includes:
- RMXCommonMethods
- Defined in:
- lib/motion/RMXFirebaseCollection.rb
Instance Attribute Summary collapse
-
#ref ⇒ Object
readonly
Returns the value of attribute ref.
-
#snaps ⇒ Object
readonly
Returns the value of attribute snaps.
Class Method Summary collapse
-
.get(ref) ⇒ Object
this is the method you should call.
- .identity_map ⇒ Object
- .new(ref) ⇒ Object
Instance Method Summary collapse
- #_clear_current_ref! ⇒ Object
- #_log_hash(hash) ⇒ Object
- #_log_snap_names ⇒ Object
-
#_test_scatter! ⇒ Object
mess up the order on purpose.
-
#add(snap, prev) ⇒ Object
internal.
-
#added(queue = nil, &block) ⇒ Object
completes with ‘self`, `snap`, `prev` every time the collection :added fires.
-
#always(queue = nil, &block) ⇒ Object
completes with ‘self` immediately if ready, and every time the collection :ready fires.
- #always_async(&block) ⇒ Object
-
#cancelled! ⇒ Object
internal.
-
#cancelled? ⇒ Boolean
public.
-
#changed(queue = nil, &block) ⇒ Object
completes with ‘self` every time the collection :changed fires.
-
#initialize ⇒ RMXFirebaseCollection
constructor
internal.
-
#moved(queue = nil, &block) ⇒ Object
completes with ‘self`, `snap`, `prev` every time the collection :moved fires.
-
#once(queue = nil, &block) ⇒ Object
completes with ‘self` once, when the collection is ready.
- #once_async(&block) ⇒ Object
-
#ready! ⇒ Object
internal.
-
#ready? ⇒ Boolean
public.
- #refresh_order! ⇒ Object
-
#remove(snap) ⇒ Object
internal.
-
#removed(queue = nil, &block) ⇒ Object
completes with ‘self`, `snap` every time the collection :removed fires.
- #rmx_dealloc ⇒ Object
-
#setup_ref(_ref) ⇒ Object
internal.
-
#store_transform(snap) ⇒ Object
internal.
-
#transform(snap) ⇒ Object
overridable.
-
#transform=(block) ⇒ Object
internal, allows the user to pass a block for transformations instead of subclassing and overriding #transform, for one-off cases.
-
#transformed(queue = nil, &block) ⇒ Object
public, completes with ready transformations.
- #transformed_async(&block) ⇒ Object
Constructor Details
#initialize ⇒ RMXFirebaseCollection
internal
114 115 116 117 118 119 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 114 def initialize @snaps_by_name = {} @snaps = [] @transformations_table = {} @transformations = [] end |
Instance Attribute Details
#ref ⇒ Object (readonly)
Returns the value of attribute ref.
5 6 7 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 5 def ref @ref end |
#snaps ⇒ Object (readonly)
Returns the value of attribute snaps.
5 6 7 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 5 def snaps @snaps end |
Class Method Details
.get(ref) ⇒ Object
this is the method you should call
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 346 def self.get(ref) if ref && existing = identity_map[[ className, ref.description ]] if RMXFirebase::DEBUG_IDENTITY_MAP p "HIT!", className, ref.description, existing.retainCount end return existing else if RMXFirebase::DEBUG_IDENTITY_MAP p "MISS!", className, ref.description end res = new(ref) if ref identity_map[[ className, ref.description ]] = res end res end end |
.identity_map ⇒ Object
368 369 370 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 368 def self.identity_map @@identity_map end |
.new(ref) ⇒ Object
105 106 107 108 109 110 111 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 105 def self.new(ref) x = super() RMXFirebase::QUEUE. do x.setup_ref(ref) end x end |
Instance Method Details
#_clear_current_ref! ⇒ Object
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 194 def _clear_current_ref! if @ref if @added_handler @ref.off(@added_handler) @added_handler = nil end if @removed_handler @ref.off(@removed_handler) @removed_handler = nil end if @moved_handler @ref.off(@moved_handler) @moved_handler = nil end if @value_handler @ref.off(@value_handler) @value_handler = nil end @ref = nil end end |
#_log_hash(hash) ⇒ Object
260 261 262 263 264 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 260 def _log_hash(hash) hash.to_a.sort_by { |x| x[1] }.each do |pair| puts pair.inspect end end |
#_log_snap_names ⇒ Object
252 253 254 255 256 257 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 252 def _log_snap_names RMXFirebase::QUEUE. do puts "snaps_by_name:" _log_hash(@snaps_by_name) end end |
#_test_scatter! ⇒ Object
mess up the order on purpose
176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 176 def _test_scatter! RMXFirebase::QUEUE. do _snaps = @snaps.dup p "before scatter", @snaps.map(&:name) p "before scatter snaps_by_name", @snaps_by_name _snaps.each do |snap| others = _snaps - [ snap ] random = others.sample add(snap, random.name) end end end |
#add(snap, prev) ⇒ Object
internal
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 267 def add(snap, prev) RMX(self).require_queue!(RMXFirebase::QUEUE, __FILE__, __LINE__) if RMX::DEBUG_QUEUES moved = false if current_index = @snaps_by_name[snap.name] if current_index == 0 && prev.nil? return elsif current_index > 0 && prev && @snaps_by_name[prev] == current_index - 1 return end moved = true @snaps.delete_at(current_index) @transformations.delete_at(current_index) if was_index = @snaps_by_name.delete(snap.name) @snaps_by_name.keys.each do |k| v = @snaps_by_name[k] if v > was_index @snaps_by_name[k] -= 1 end end end # raise if snaps_by_name.values.uniq.size != snaps_by_name.values.size end # raise if snaps_by_name.values.uniq.size != snaps_by_name.values.size if prev && (index = @snaps_by_name[prev]) new_index = index + 1 @snaps.insert(new_index, snap) @transformations.insert(new_index, store_transform(snap)) @snaps_by_name.keys.each do |k| v = @snaps_by_name[k] if v >= new_index @snaps_by_name[k] += 1 end end @snaps_by_name[snap.name] = new_index # raise if snaps_by_name.values.uniq.size != snaps_by_name.values.size else @snaps.unshift(snap) @transformations.unshift(store_transform(snap)) @snaps_by_name.keys.each do |k| v = @snaps_by_name[k] @snaps_by_name[k] += 1 end @snaps_by_name[snap.name] = 0 # raise if snaps_by_name.values.uniq.size != snaps_by_name.values.size end if moved RMX(self).trigger(:moved, self, snap, prev) else RMX(self).trigger(:added, self, snap, prev) end RMX(self).trigger(:changed, self) if ready? RMX(self).trigger(:ready, self) RMX(self).trigger(:finished, self) end end |
#added(queue = nil, &block) ⇒ Object
completes with ‘self`, `snap`, `prev` every time the collection :added fires. does not retain `self` or the sender. returns an “unbinder” that can be called to stop listening.
84 85 86 87 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 84 def added(queue=nil, &block) return false if cancelled? RMX(self).on(:added, :queue => queue, &block) end |
#always(queue = nil, &block) ⇒ Object
completes with ‘self` immediately if ready, and every time the collection :ready fires. does not retain `self` or the sender. returns an “unbinder” that can be called to stop listening.
65 66 67 68 69 70 71 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 65 def always(queue=nil, &block) return false if cancelled? if ready? RMXFirebase.block_on_queue(queue, self, &block) end RMX(self).on(:ready, :queue => queue, &block) end |
#always_async(&block) ⇒ Object
58 59 60 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 58 def always_async(&block) always(:async, &block) end |
#cancelled! ⇒ Object
internal
228 229 230 231 232 233 234 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 228 def cancelled! RMXFirebase::QUEUE. do @cancelled = true RMX(self).trigger(:cancelled, self) RMX(self).trigger(:finished, self) end end |
#cancelled? ⇒ Boolean
public
13 14 15 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 13 def cancelled? !!@cancelled end |
#changed(queue = nil, &block) ⇒ Object
completes with ‘self` every time the collection :changed fires. does not retain `self` or the sender. returns an “unbinder” that can be called to stop listening.
76 77 78 79 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 76 def changed(queue=nil, &block) return false if cancelled? RMX(self).on(:changed, :queue => queue, &block) end |
#moved(queue = nil, &block) ⇒ Object
completes with ‘self`, `snap`, `prev` every time the collection :moved fires. does not retain `self` or the sender. returns an “unbinder” that can be called to stop listening.
100 101 102 103 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 100 def moved(queue=nil, &block) return false if cancelled? RMX(self).on(:moved, :queue => queue, &block) end |
#once(queue = nil, &block) ⇒ Object
completes with ‘self` once, when the collection is ready. retains `self` and the sender until complete
47 48 49 50 51 52 53 54 55 56 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 47 def once(queue=nil, &block) RMXFirebase::QUEUE. do if ready? RMXFirebase.block_on_queue(queue, self, &block) else RMX(self).once(:ready, :strong => true, :queue => queue, &block) end end self end |
#once_async(&block) ⇒ Object
41 42 43 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 41 def once_async(&block) once(:async, &block) end |
#ready! ⇒ Object
internal
218 219 220 221 222 223 224 225 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 218 def ready! RMXFirebase::QUEUE. do @ready = true RMX(self).trigger(:ready, self) RMX(self).trigger(:changed, self) RMX(self).trigger(:finished, self) end end |
#ready? ⇒ Boolean
public
8 9 10 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 8 def ready? !!@ready end |
#refresh_order! ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 158 def refresh_order! RMXFirebase::QUEUE. do next unless @ref if @added_handler @ref.off(@added_handler) @added_handler = nil end @added_handler = @ref.on(:added) do |snap, prev| # p "NORMAL ", snap.name, prev RMXFirebase::QUEUE. do # p "BARRIER", snap.name, prev add(snap, prev) end end end end |
#remove(snap) ⇒ Object
internal
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 326 def remove(snap) if current_index = @snaps_by_name[snap.name] @snaps.delete_at(current_index) @transformations.delete_at(current_index) @snaps_by_name.keys.each do |k| v = @snaps_by_name[k] if v > current_index @snaps_by_name[k] -= 1 end end RMX(self).trigger(:removed, self, snap) RMX(self).trigger(:changed, self) if ready? RMX(self).trigger(:ready, self) RMX(self).trigger(:finished, self) end end end |
#removed(queue = nil, &block) ⇒ Object
completes with ‘self`, `snap` every time the collection :removed fires. does not retain `self` or the sender. returns an “unbinder” that can be called to stop listening.
92 93 94 95 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 92 def removed(queue=nil, &block) return false if cancelled? RMX(self).on(:removed, :queue => queue, &block) end |
#rmx_dealloc ⇒ Object
190 191 192 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 190 def rmx_dealloc _clear_current_ref! end |
#setup_ref(_ref) ⇒ Object
internal
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 122 def setup_ref(_ref) RMX(self).require_queue!(RMXFirebase::QUEUE, __FILE__, __LINE__) if RMX::DEBUG_QUEUES _clear_current_ref! @ref = _ref @ready = false @cancelled = false cancel_block = lambda do |err| @cancelled = err cancelled! end @added_handler = @ref.on(:added) do |snap, prev| # p "NORMAL ", snap.name, prev RMXFirebase::QUEUE. do # p "BARRIER", snap.name, prev add(snap, prev) end end @removed_handler = @ref.on(:removed) do |snap| RMXFirebase::QUEUE. do remove(snap) end end @moved_handler = @ref.on(:moved) do |snap, prev| RMXFirebase::QUEUE. do add(snap, prev) end end @value_handler = @ref.once(:value, { :disconnect => cancel_block }) do |collection| @value_handler = nil RMXFirebase::QUEUE. do ready! end end RMX(self).on(:cancelled, :exclusive => [ :ready, :finished, :changed, :added, :removed, :moved ], :queue => :async) end |
#store_transform(snap) ⇒ Object
internal
247 248 249 250 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 247 def store_transform(snap) RMX(self).require_queue!(RMXFirebase::QUEUE, __FILE__, __LINE__) if RMX::DEBUG_QUEUES @transformations_table[snap] ||= transform(snap) end |
#transform(snap) ⇒ Object
overridable
18 19 20 21 22 23 24 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 18 def transform(snap) if block = @transform_block block.call(snap) else snap end end |
#transform=(block) ⇒ Object
internal, allows the user to pass a block for transformations instead of subclassing and overriding #transform, for one-off cases
238 239 240 241 242 243 244 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 238 def transform=(block) if block @transform_block = RMX.safe_block(block) else @transform_block = nil end end |
#transformed(queue = nil, &block) ⇒ Object
public, completes with ready transformations
31 32 33 34 35 36 37 38 39 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 31 def transformed(queue=nil, &block) items = @transformations.dup if (snap = items.first) && snap.is_a?(RMXFirebaseModel) RMXFirebaseBatch.new(items).once(queue, &block) else RMXFirebase.block_on_queue(queue, items, &block) end self end |
#transformed_async(&block) ⇒ Object
26 27 28 |
# File 'lib/motion/RMXFirebaseCollection.rb', line 26 def transformed_async(&block) transformed(:async, &block) end |