Class: LazyArray

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/dm-core/support/lazy_array.rb

Overview

borrowed partially from StrokeDB

Direct Known Subclasses

DataMapper::Collection

Instance Attribute Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (private)

delegate any not-explicitly-handled methods to @array, if possible. this is handy for handling methods mixed-into Array like group_by



420
421
422
423
424
425
426
427
428
# File 'lib/dm-core/support/lazy_array.rb', line 420

def method_missing(method, *args, &block)
  if @array.respond_to?(method)
    lazy_load
    results = @array.send(method, *args, &block)
    results.equal?(@array) ? self : results
  else
    super
  end
end

Instance Attribute Details

#headObject (readonly)

Returns the value of attribute head



4
5
6
# File 'lib/dm-core/support/lazy_array.rb', line 4

def head
  @head
end

#tailObject (readonly)

Returns the value of attribute tail



4
5
6
# File 'lib/dm-core/support/lazy_array.rb', line 4

def tail
  @tail
end

Instance Method Details

#<<(entry) ⇒ Object



169
170
171
172
173
174
175
176
177
# File 'lib/dm-core/support/lazy_array.rb', line 169

def <<(entry)
  if loaded?
    lazy_load
    @array << entry
  else
    @tail << entry
  end
  self
end

#==(other) ⇒ Object



315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/dm-core/support/lazy_array.rb', line 315

def ==(other)
  if equal?(other)
    return true
  end

  unless other.respond_to?(:to_ary)
    return false
  end

  # if necessary, convert to something that can be compared
  other = other.to_ary unless other.respond_to?(:[])

  cmp?(other, :==)
end

#[](*args) ⇒ Object Also known as: slice



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/dm-core/support/lazy_array.rb', line 100

def [](*args)
  index, length = extract_slice_arguments(*args)

  if length == 1 && args.size == 1 && args.first.kind_of?(Integer)
    return at(index)
  end

  if index >= 0 && lazy_possible?(@head, index + length)
    @head[*args]
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
    @tail[*args]
  else
    lazy_load
    @array[*args]
  end
end

#[]=(*args) ⇒ Object Also known as: splice



132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/dm-core/support/lazy_array.rb', line 132

def []=(*args)
  index, length = extract_slice_arguments(*args[0..-2])

  if index >= 0 && lazy_possible?(@head, index + length)
    @head.[]=(*args)
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
    @tail.[]=(*args)
  else
    lazy_load
    @array.[]=(*args)
  end
end

#any?(&block) ⇒ Boolean

Returns:

  • (Boolean)


92
93
94
95
96
97
98
# File 'lib/dm-core/support/lazy_array.rb', line 92

def any?(&block)
  (lazy_possible?(@tail) && @tail.any?(&block)) ||
  (lazy_possible?(@head) && @head.any?(&block)) || begin
    lazy_load
    @array.any?(&block)
  end
end

#at(index) ⇒ Object



24
25
26
27
28
29
30
31
32
33
# File 'lib/dm-core/support/lazy_array.rb', line 24

def at(index)
  if index >= 0 && lazy_possible?(@head, index + 1)
    @head.at(index)
  elsif index < 0 && lazy_possible?(@tail, index.abs)
    @tail.at(index)
  else
    lazy_load
    @array.at(index)
  end
end

#clearObject



268
269
270
271
272
# File 'lib/dm-core/support/lazy_array.rb', line 268

def clear
  mark_loaded
  @array.clear
  self
end

#concat(other) ⇒ Object



179
180
181
182
183
184
185
186
187
# File 'lib/dm-core/support/lazy_array.rb', line 179

def concat(other)
  if loaded?
    lazy_load
    @array.concat(other)
  else
    @tail.concat(other)
  end
  self
end

#delete_at(index) ⇒ Object



239
240
241
242
243
244
245
246
247
248
# File 'lib/dm-core/support/lazy_array.rb', line 239

def delete_at(index)
  if index >= 0 && lazy_possible?(@head, index + 1)
    @head.delete_at(index)
  elsif index < 0 && lazy_possible?(@tail, index.abs)
    @tail.delete_at(index)
  else
    lazy_load
    @array.delete_at(index)
  end
end

#delete_if(&block) ⇒ Object



250
251
252
253
254
255
256
257
258
259
260
# File 'lib/dm-core/support/lazy_array.rb', line 250

def delete_if(&block)
  if loaded?
    lazy_load
    @array.delete_if(&block)
  else
    @reapers << block
    @head.delete_if(&block)
    @tail.delete_if(&block)
  end
  self
end

#empty?Boolean

Returns:

  • (Boolean)


84
85
86
87
88
89
90
# File 'lib/dm-core/support/lazy_array.rb', line 84

def empty?
  (@tail.nil? || @tail.empty?) &&
  (@head.nil? || @head.empty?) && begin
    lazy_load
    @array.empty?
  end
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


330
331
332
333
334
335
336
337
338
339
340
# File 'lib/dm-core/support/lazy_array.rb', line 330

def eql?(other)
  if equal?(other)
    return true
  end

  unless other.class.equal?(self.class)
    return false
  end

  cmp?(other, :eql?)
end

#fetch(*args, &block) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/dm-core/support/lazy_array.rb', line 35

def fetch(*args, &block)
  index = args.first

  if index >= 0 && lazy_possible?(@head, index + 1)
    @head.fetch(*args, &block)
  elsif index < 0 && lazy_possible?(@tail, index.abs)
    @tail.fetch(*args, &block)
  else
    lazy_load
    @array.fetch(*args, &block)
  end
end

#first(*args) ⇒ Object



6
7
8
9
10
11
12
13
# File 'lib/dm-core/support/lazy_array.rb', line 6

def first(*args)
  if lazy_possible?(@head, *args)
    @head.first(*args)
  else
    lazy_load
    @array.first(*args)
  end
end

#freezeObject



300
301
302
303
304
305
306
307
308
309
# File 'lib/dm-core/support/lazy_array.rb', line 300

def freeze
  if loaded?
    @array.freeze
  else
    @head.freeze
    @tail.freeze
  end
  @frozen = true
  self
end

#frozen?Boolean

Returns:

  • (Boolean)


311
312
313
# File 'lib/dm-core/support/lazy_array.rb', line 311

def frozen?
  @frozen == true
end

#include?(entry) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
79
80
81
82
# File 'lib/dm-core/support/lazy_array.rb', line 76

def include?(entry)
  (lazy_possible?(@tail) && @tail.include?(entry)) ||
  (lazy_possible?(@head) && @head.include?(entry)) || begin
    lazy_load
    @array.include?(entry)
  end
end

#index(entry) ⇒ Object



69
70
71
72
73
74
# File 'lib/dm-core/support/lazy_array.rb', line 69

def index(entry)
  (lazy_possible?(@head) && @head.index(entry)) || begin
    lazy_load
    @array.index(entry)
  end
end

#insert(index, *entries) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
# File 'lib/dm-core/support/lazy_array.rb', line 209

def insert(index, *entries)
  if index >= 0 && lazy_possible?(@head, index)
    @head.insert(index, *entries)
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1)
    @tail.insert(index, *entries)
  else
    lazy_load
    @array.insert(index, *entries)
  end
  self
end

#kind_of?(klass) ⇒ Boolean Also known as: is_a?

Returns:

  • (Boolean)


290
291
292
# File 'lib/dm-core/support/lazy_array.rb', line 290

def kind_of?(klass)
  super || @array.kind_of?(klass)
end

#last(*args) ⇒ Object



15
16
17
18
19
20
21
22
# File 'lib/dm-core/support/lazy_array.rb', line 15

def last(*args)
  if lazy_possible?(@tail, *args)
    @tail.last(*args)
  else
    lazy_load
    @array.last(*args)
  end
end

#lazy_possible?(list, need_length = 1) ⇒ Boolean

Returns:

  • (Boolean)


342
343
344
# File 'lib/dm-core/support/lazy_array.rb', line 342

def lazy_possible?(list, need_length = 1)
  !loaded? && need_length <= list.size
end

#load_with(&block) ⇒ Object



281
282
283
284
# File 'lib/dm-core/support/lazy_array.rb', line 281

def load_with(&block)
  @load_with_proc = block
  self
end

#loaded?Boolean

Returns:

  • (Boolean)


286
287
288
# File 'lib/dm-core/support/lazy_array.rb', line 286

def loaded?
  @loaded == true
end

#pop(*args) ⇒ Object



221
222
223
224
225
226
227
228
# File 'lib/dm-core/support/lazy_array.rb', line 221

def pop(*args)
  if lazy_possible?(@tail, *args)
    @tail.pop(*args)
  else
    lazy_load
    @array.pop(*args)
  end
end

#push(*entries) ⇒ Object



189
190
191
192
193
194
195
196
197
# File 'lib/dm-core/support/lazy_array.rb', line 189

def push(*entries)
  if loaded?
    lazy_load
    @array.push(*entries)
  else
    @tail.push(*entries)
  end
  self
end

#replace(other) ⇒ Object



262
263
264
265
266
# File 'lib/dm-core/support/lazy_array.rb', line 262

def replace(other)
  mark_loaded
  @array.replace(other)
  self
end

#respond_to?(method, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


296
297
298
# File 'lib/dm-core/support/lazy_array.rb', line 296

def respond_to?(method, include_private = false)
  super || @array.respond_to?(method)
end

#reverseObject



147
148
149
# File 'lib/dm-core/support/lazy_array.rb', line 147

def reverse
  dup.reverse!
end

#reverse!Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/dm-core/support/lazy_array.rb', line 151

def reverse!
  # reverse without kicking if possible
  if loaded?
    @array = @array.reverse
  else
    @head, @tail = @tail.reverse, @head.reverse

    proc = @load_with_proc

    @load_with_proc = lambda do |v|
      proc.call(v)
      v.instance_variable_get(:@array).reverse!
    end
  end

  self
end

#shift(*args) ⇒ Object



230
231
232
233
234
235
236
237
# File 'lib/dm-core/support/lazy_array.rb', line 230

def shift(*args)
  if lazy_possible?(@head, *args)
    @head.shift(*args)
  else
    lazy_load
    @array.shift(*args)
  end
end

#slice!(*args) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/dm-core/support/lazy_array.rb', line 119

def slice!(*args)
  index, length = extract_slice_arguments(*args)

  if index >= 0 && lazy_possible?(@head, index + length)
    @head.slice!(*args)
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
    @tail.slice!(*args)
  else
    lazy_load
    @array.slice!(*args)
  end
end

#to_aObject Also known as: to_ary



274
275
276
277
# File 'lib/dm-core/support/lazy_array.rb', line 274

def to_a
  lazy_load
  @array.to_a
end

#unshift(*entries) ⇒ Object



199
200
201
202
203
204
205
206
207
# File 'lib/dm-core/support/lazy_array.rb', line 199

def unshift(*entries)
  if loaded?
    lazy_load
    @array.unshift(*entries)
  else
    @head.unshift(*entries)
  end
  self
end

#values_at(*args) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/dm-core/support/lazy_array.rb', line 48

def values_at(*args)
  accumulator = []

  lazy_possible = args.all? do |arg|
    index, length = extract_slice_arguments(arg)

    if index >= 0 && lazy_possible?(@head, index + length)
      accumulator.concat(head.values_at(*arg))
    elsif index < 0 && lazy_possible?(@tail, index.abs)
      accumulator.concat(tail.values_at(*arg))
    end
  end

  if lazy_possible
    accumulator
  else
    lazy_load
    @array.values_at(*args)
  end
end