Class: Spider::Model::QuerySet

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/spiderfw/model/query_set.rb

Overview

The QuerySet expresses represents a Query applied on a Model. It includes Enumerable, and can be accessed as an Array; but, the QuerySet is lazy, and the actual data will be fetched only when actually requested, or when a #load is issued. How much data is fetched and kept in memory can be controlled by setting the #fetch_window and the #keep_window.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, query_or_val = nil) ⇒ QuerySet

The first argument must be a BaseModel subclass. The second argument may be a Query, or data that will be passed to #set_data. If data is passed, the QuerySet will be instantiated with autoload set to false.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/spiderfw/model/query_set.rb', line 71

def initialize(model, query_or_val=nil)
    @model = model
    model.extend_queryset(self)
    if (model.attributes[:integrated_models])
        model.attributes[:integrated_models].each{ |m, el| m.extend_queryset(self) }
    end
    if (query_or_val.is_a?(Query))
         query = query_or_val 
    else
        data = query_or_val
    end
    @query = query || Query.new
    @objects = []
    @raw_data = []
    @_parent = nil
    @_parent_element = nil
    @index_lookup = {}
    @total_rows = nil
    @fetch_window = nil
    @window_current_start = nil
    @keep_window = 100
    @autoload = query_or_val.is_a?(Query) ? true : false
    @identity_mapper = nil
    @loaded = false
    @loaded_elements = {}
    @fixed = {}
    @append_element = nil
    @loadable = true
    set_data(data) if data
    self
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &proc) ⇒ Object



714
715
716
717
718
719
720
721
# File 'lib/spiderfw/model/query_set.rb', line 714

def method_missing(method, *args, &proc)
    el = @model.elements[method]
    if (el && el.model? && el.reverse)
        return element_queryset(el)
    end
    return @query.send(method, *args, &proc) if @query.respond_to?(method)
    return super
end

Instance Attribute Details

#_no_identity_mapperObject

Don’t put this queryset’s objects into the IdentityMapper



52
53
54
# File 'lib/spiderfw/model/query_set.rb', line 52

def _no_identity_mapper
  @_no_identity_mapper
end

#_no_parentObject

Disables parent setting for this QuerySet



15
16
17
# File 'lib/spiderfw/model/query_set.rb', line 15

def _no_parent
  @_no_parent
end

#_parentObject

BaseModel instance pointing to this QuerySet



11
12
13
# File 'lib/spiderfw/model/query_set.rb', line 11

def _parent
  @_parent
end

#_parent_elementObject

Element inside the _parent pointing to this QuerySet.



13
14
15
# File 'lib/spiderfw/model/query_set.rb', line 13

def _parent_element
  @_parent_element
end

#append_elementObject

If something that can’t be converted to a @model instance is appended to the QuerySet, and append_element is set, the appended value will be set on the element named append_element of a new instance of @model, which will be appended instead. This is useful for junction models, which function as both types. Example:

cat = Animal.new; tiger = Animal.new;
# Instead of doing
friend = Animal::Friend.new(:animal => cat, :other_animal => tiger)
cat.friends << friend
# since the junction was created setting append_element = :other_animal, one can do
cat.friends << lion


48
49
50
# File 'lib/spiderfw/model/query_set.rb', line 48

def append_element
  @append_element
end

#fetch_windowObject

(Fixnum) How many objects to load at a time. If nil, all the objects returned by the Query will be loaded.



34
35
36
# File 'lib/spiderfw/model/query_set.rb', line 34

def fetch_window
  @fetch_window
end

#keep_windowObject

(Fixnum) How many objects to keep in memory when advancing the window. If nil, all objects will be kept.



36
37
38
# File 'lib/spiderfw/model/query_set.rb', line 36

def keep_window
  @keep_window
end

#last_queryObject

Set by mapper



25
26
27
# File 'lib/spiderfw/model/query_set.rb', line 25

def last_query
  @last_query
end

#loadableObject

(bool) If false, prevents the QuerySet from loading.



50
51
52
# File 'lib/spiderfw/model/query_set.rb', line 50

def loadable
  @loadable
end

#loadedObject

(bool) Wether the QuerySet has been loaded



31
32
33
# File 'lib/spiderfw/model/query_set.rb', line 31

def loaded
  @loaded
end

#loaded_elementsObject (readonly)

An Hash of autoloaded elements.



19
20
21
# File 'lib/spiderfw/model/query_set.rb', line 19

def loaded_elements
  @loaded_elements
end

#modelObject

The BaseModel



27
28
29
# File 'lib/spiderfw/model/query_set.rb', line 27

def model
  @model
end

#modifiedObject

Returns the value of attribute modified.



53
54
55
# File 'lib/spiderfw/model/query_set.rb', line 53

def modified
  @modified
end

#objectsObject (readonly)

The actual fetched objects.



21
22
23
# File 'lib/spiderfw/model/query_set.rb', line 21

def objects
  @objects
end

#queryObject

The Query



23
24
25
# File 'lib/spiderfw/model/query_set.rb', line 23

def query
  @query
end

#raw_dataObject (readonly)

Raw data returned by the mapper, if requested.



17
18
19
# File 'lib/spiderfw/model/query_set.rb', line 17

def raw_data
  @raw_data
end

#total_rowsObject

Total number of objects that would be returned had the Query no limit.



29
30
31
# File 'lib/spiderfw/model/query_set.rb', line 29

def total_rows
  @total_rows
end

Class Method Details

.autoloading(model, query_or_val = nil) ⇒ Object



62
63
64
65
66
# File 'lib/spiderfw/model/query_set.rb', line 62

def self.autoloading(model, query_or_val=nil)
    qs = self.new(model, query_or_val)
    qs.autoload = true
    return qs
end

.static(model, query_or_val = nil) ⇒ Object

Instantiates a non-autoloading queryset



56
57
58
59
60
# File 'lib/spiderfw/model/query_set.rb', line 56

def self.static(model, query_or_val=nil)
    qs = self.new(model, query_or_val)
    qs.autoload = false
    return qs
end

Instance Method Details

#+(other) ⇒ Object

Returns a new QuerySet containing objects from both this and the other.



250
251
252
253
254
255
256
# File 'lib/spiderfw/model/query_set.rb', line 250

def +(other)
    qs = self.clone
    other.each do |obj|
        qs << obj
    end
    return qs
end

#<<(obj, raw = nil) ⇒ Object

Adds an object to the set. Also stores the raw data if it is passed as the second parameter.



165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/spiderfw/model/query_set.rb', line 165

def <<(obj, raw=nil)
    return merge(obj) if (obj.class == QuerySet)
    unless (obj.is_a?(@model))
        obj = instantiate_object(obj)
    end
    @objects << obj
    @fixed.each do |key, val|
        obj.set(key, val)
    end
    index_object(obj)
    @raw_data[@objects.length-1] = raw if raw
    @modified = true
end

#[](index) ⇒ Object

Accesses an object. Data will be loaded according to fetch_window.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/spiderfw/model/query_set.rb', line 181

def [](index)
    if (index.is_a?(Range))
        return index.map{ |i| self[i] }
    elsif (index.is_a?(String))
        i, rest = index.split('.', 2)
        i = i.to_i
        val = self[i]
        return '' unless val
        return val[rest]
    end
    start = start_for_index(index)
    array_index = (index - start) + 1
    load_to_index(index) unless (@objects[array_index] && (!@fetch_window || @window_current_start == start)) || loaded?(index) || !autoload?
    val = @objects[array_index]
    val.set_parent(self, nil) if val && !@_no_parent
    return val
end

#[]=(index, val) ⇒ Object

Sets an object.



200
201
202
203
204
205
206
207
208
209
# File 'lib/spiderfw/model/query_set.rb', line 200

def []=(index, val)
    #load_to_index(index) unless loaded?(index) || !autoload?
    val = instantiate_object(val) unless val.is_a?(@model)
    @fixed.each do |fkey, fval|
        val.set(fkey, fval)
    end
    array_index = index
    array_index -= @window_current_start-1 if @window_current_start
    @objects[array_index] = val
end

#all_children(path) ⇒ Object

Given a dotted path, will return an array of all objects reachable by that path Example

objectset.all_children('friends.collegues.addresses.street_name')


738
739
740
741
742
743
744
# File 'lib/spiderfw/model/query_set.rb', line 738

def all_children(path)
    if (path.length > 0)
        children = @objects.map{ |obj| obj.all_children(path.clone) }.flatten
    else
        return @objects
    end
end

#autoload(bool, traverse = true) ⇒ Object

Enables or disables autoload; if the second argument is true, will traverse contained objects.



116
117
118
119
# File 'lib/spiderfw/model/query_set.rb', line 116

def autoload(bool, traverse=true)
    @autoload = bool
    @objects.each{ |obj| obj.autoload = bool } if traverse
end

#autoload=(bool) ⇒ Object

Enables or disables autoload.



122
123
124
# File 'lib/spiderfw/model/query_set.rb', line 122

def autoload=(bool)
    autoload(bool)
end

#autoload?Boolean

Returns:

  • (Boolean)


126
127
128
# File 'lib/spiderfw/model/query_set.rb', line 126

def autoload?
    @autoload ? true : false
end

#change_model(model) ⇒ Object



156
157
158
159
160
161
162
# File 'lib/spiderfw/model/query_set.rb', line 156

def change_model(model)
    @model = model
    @objects.each_index do |i|
        @objects[i] = @objects[i].become(model)
    end
    return self
end

#clearObject

Remove all elements from self



349
350
351
352
# File 'lib/spiderfw/model/query_set.rb', line 349

def clear
    @objects = []
    @index_lookup.each_key{ |k| @index_lookup[k] = {} }
end

#cloneObject

Performs a deep copy



811
812
813
814
815
816
817
818
819
# File 'lib/spiderfw/model/query_set.rb', line 811

def clone
    c = self.class.new(self.model, self.query.clone)
    c.autoload = self.autoload?
    c_objects = c.instance_variable_get(:@objects)
    @objects.each do |o|
        c_objects << o.clone
    end
    return c
end

#command_exists?(command) ⇒ Boolean

Determines if a shell command exists by searching for it in ENV.

Returns:

  • (Boolean)


610
611
612
# File 'lib/spiderfw/model/query_set.rb', line 610

def command_exists?(command)
  ENV['PATH'].split(File::PATH_SEPARATOR).any? {|d| File.exists? File.join(d, command) }
end

#current_lengthObject

Current number of objects fetched.



288
289
290
# File 'lib/spiderfw/model/query_set.rb', line 288

def current_length
    @objects.length
end

#currently_empty?Boolean

Returns:

  • (Boolean)


298
299
300
# File 'lib/spiderfw/model/query_set.rb', line 298

def currently_empty?
    @objects.empty?
end

#cut(*params) ⇒ Object

Returns an array with the results of calling #BaseModel.cut on each object.



584
585
586
587
# File 'lib/spiderfw/model/query_set.rb', line 584

def cut(*params)
    load unless loaded? || !autoload?
    return self.map{ |obj| obj.cut(*params) }
end

#delete(obj) ⇒ Object



245
246
247
# File 'lib/spiderfw/model/query_set.rb', line 245

def delete(obj)
    @objects.delete(obj)
end

#delete_at(index) ⇒ Object

Deletes object at the given index.



241
242
243
# File 'lib/spiderfw/model/query_set.rb', line 241

def delete_at(index)
    @objects.delete_at(index)
end

#detect_terminal_sizeObject

Returns [width, height] of terminal when detected, nil if not detected. Think of this as a simpler version of Highline’s Highline::SystemExtensions.terminal_size()



616
617
618
619
620
621
622
623
624
625
626
# File 'lib/spiderfw/model/query_set.rb', line 616

def detect_terminal_size
  if (ENV['COLUMNS'] =~ /^\d+$/) && (ENV['LINES'] =~ /^\d+$/)
    [ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
  elsif (RUBY_PLATFORM =~ /java/ || !STDIN.tty?) && command_exists?('tput')
    [`tput cols`.to_i, `tput lines`.to_i]
  else
    command_exists?('stty') ? `stty size`.scan(/\d+/).map { |s| s.to_i }.reverse : nil
  end
rescue
  nil
end

#eachObject

Iterates on objects, loading when needed.



360
361
362
363
364
365
366
367
368
369
# File 'lib/spiderfw/model/query_set.rb', line 360

def each
    self.each_rolling_index do |i|
        obj = @objects[i]
        prev_parent = obj._parent
        prev_parent_element = obj._parent_element
        obj.set_parent(self, nil)
        yield obj
        obj.set_parent(prev_parent, prev_parent_element)
    end
end

#each_currentObject

Iterates on currently loaded objects



355
356
357
# File 'lib/spiderfw/model/query_set.rb', line 355

def each_current
    @objects.each { |obj| yield obj }
end

#each_current_indexObject

Iterates on indexes without loading.



393
394
395
396
397
398
# File 'lib/spiderfw/model/query_set.rb', line 393

def each_current_index
    @objects.each_index do |i|
        i += @window_current_start-1 if @window_current_start
        yield i
    end
end

#each_indexObject

Iterates yielding the queryset index. Will load when needed.



385
386
387
388
389
390
# File 'lib/spiderfw/model/query_set.rb', line 385

def each_index
    self.each_rolling_index do |i|
        i += @window_current_start-1 if @window_current_start
        yield i
    end
end

#each_rolling_indexObject

Iterates yielding the internal objects index. Will load when needed. If a window is used, the index will roll back to 0 on every window.



373
374
375
376
377
378
379
380
381
382
# File 'lib/spiderfw/model/query_set.rb', line 373

def each_rolling_index
    @window_current_start = nil if (@fetch_window)
    while (!@fetch_window || has_more?)
        load_next unless !autoload? || (!@fetch_window && @loaded)
        @objects.each_index do |i|
            yield i
        end
        break unless autoload? && @fetch_window
    end
end

#element_loaded(element) ⇒ Object

Registers that the element has been loaded.



747
748
749
750
# File 'lib/spiderfw/model/query_set.rb', line 747

def element_loaded(element)
    element = element.name if element.is_a?(Element)
    @loaded_elements[element] = true
end

#element_loaded?(element) ⇒ Boolean

Returns whether the element has been loaded from the Storage.

Returns:

  • (Boolean)


753
754
755
756
# File 'lib/spiderfw/model/query_set.rb', line 753

def element_loaded?(element)
    element = element.name if element.is_a?(Element)
    @loaded_elements[element]
end

#element_queryset(el) ⇒ Object



723
724
725
726
727
728
729
730
731
732
733
# File 'lib/spiderfw/model/query_set.rb', line 723

def element_queryset(el)
    el = @model.elements[el] if el.is_a?(Symbol)
    condition = el.condition
    if (el.attributes[:element_query])
        el = @model.elements[el.attributes[:element_query]]
    end
    cond = Spider::Model::Condition.new
    cond[el.reverse] = self.map_current{ |row| row }
    cond = cond.and(condition) if (condition)
    return self.class.new(el.model, Query.new(cond))
end

#empty!Object



706
707
708
# File 'lib/spiderfw/model/query_set.rb', line 706

def empty!
    @objects = []
end

#empty?Boolean

True if no objects were fetched (yet).

Returns:

  • (Boolean)


293
294
295
296
# File 'lib/spiderfw/model/query_set.rb', line 293

def empty?
    load unless @loaded || !autoload?
    @objects.empty?
end

#find(params) ⇒ Object

Searchs the index for objects matching the given params.

Raises:

  • (UnimplementedError)


427
428
429
430
431
432
433
434
435
436
437
# File 'lib/spiderfw/model/query_set.rb', line 427

def find(params)
    sorted_keys = params.keys.map{|k| k.to_s}.sort.map{|k| k.to_sym}
    index = sorted_keys.map{ |key| key.to_s }.join(',')
    search_key = sorted_keys.map{ |key| search_key(params, key) }.join(',')
    # TODO: implement find without index
    raise UnimplementedError, "find without an index is not yet implemented" unless @index_lookup[index]
    result = @index_lookup[index][search_key]
    #result = QuerySet.new(result) if (result)
    #@objects = result
    return QuerySet.new(@model, result)
end

#fixed(name, value) ⇒ Object

Sets a fixed value: it will be applied to every object.



110
111
112
# File 'lib/spiderfw/model/query_set.rb', line 110

def fixed(name, value)
    @fixed[name] = value
end

#has_more?Boolean

True if the query had a limit, and more results can be fetched.

Returns:

  • (Boolean)


275
276
277
278
279
280
# File 'lib/spiderfw/model/query_set.rb', line 275

def has_more?
    return true if autoload? && !@loaded
    return false unless query.limit
    pos = query.offset.to_i + length
    return pos < total_rows
end

#identity_mapperObject

Returns the QuerySet IdentityMapper instance



759
760
761
762
# File 'lib/spiderfw/model/query_set.rb', line 759

def identity_mapper
    return Spider::Model.identity_mapper if Spider::Model.identity_mapper
    @identity_mapper ||= IdentityMapper.new
end

#identity_mapper=(im) ⇒ Object

Assigns an IdentityMapper



765
766
767
# File 'lib/spiderfw/model/query_set.rb', line 765

def identity_mapper=(im)
    @identity_mapper = im
end

#include?(val) ⇒ Boolean

Returns:

  • (Boolean)


406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# File 'lib/spiderfw/model/query_set.rb', line 406

def include?(val)
    self.each do |obj|
        if val.is_a?(BaseModel)
            return true if obj == val
        elsif val.is_a?(Hash)
            has_all = true
            val.each do |k, v|
                unless obj.get(k) == v
                    has_all = false
                    break
                end
                return true if has_all
            end
        elsif @model.primary_keys.length == 1
            return true if obj.primary_keys[0] == val
        end
    end
    return false
end

#index_by(*elements) ⇒ Object

Index objects by some elements.



303
304
305
306
307
308
309
# File 'lib/spiderfw/model/query_set.rb', line 303

def index_by(*elements)
    names = elements.map{ |el| (el.is_a?(Spider::Model::Element)) ? el.name.to_s : el.to_s }
    index_name = names.sort.join(',')
    @index_lookup[index_name] = {}
    reindex
    return self
end

#index_object(obj) ⇒ Object

Adds object to the index



323
324
325
326
327
328
329
330
331
# File 'lib/spiderfw/model/query_set.rb', line 323

def index_object(obj) # :nodoc:
    @index_lookup.keys.each do |index_by|
        names = index_by.split(',')
        search_key = names.map{ |name| 
            search_key(obj, name)
        }.join(',')
        (@index_lookup[index_by][search_key] ||= []) << obj
    end
end

#insertObject

Calls #BaseModel.insert on each object in the QuerySet.



537
538
539
# File 'lib/spiderfw/model/query_set.rb', line 537

def insert
    no_autoload(false){ each{ |obj| obj.insert } }
end

#inspectObject



570
571
572
# File 'lib/spiderfw/model/query_set.rb', line 570

def inspect
    return "#{self.class.name}:\n@model=#{@model}, @query=#{query.inspect}, @objects=#{@objects.inspect}"
end

#instantiate_object(val = nil) ⇒ Object

Returns a new instance of @model from val.



555
556
557
558
559
560
561
562
563
564
565
566
567
568
# File 'lib/spiderfw/model/query_set.rb', line 555

def instantiate_object(val=nil)
    if (@append_element && !val.is_a?(@model) && !(val.is_a?(Hash) && val[@append_element]))
        val = @model.elements[@append_element].type.new(val) unless (val.is_a?(BaseModel))
        val = {@append_element => val}
    end
        
    obj = @model.new(val)
    obj.identity_mapper = @identity_mapper
    obj.autoload = autoload?
    @fixed.each do |key, fval|
        obj.set(key, fval)
    end
    return obj
end

#lastObject

Returns the last object.



235
236
237
238
# File 'lib/spiderfw/model/query_set.rb', line 235

def last
    load unless (@loaded || !autoload?) && loaded?(total_rows-1)
    @objects.last
end

#lengthObject

Number of objects fetched. Will call load if not loaded yet. Note: this is not the total number of objects corresponding to the Query; it may be equal to the fetch_window, or to the @query.limit.



261
262
263
264
# File 'lib/spiderfw/model/query_set.rb', line 261

def length
    load unless @loaded || !autoload?
    @objects.length
end

#limit(n) ⇒ Object

Calls #Query.limit



785
786
787
788
# File 'lib/spiderfw/model/query_set.rb', line 785

def limit(n)
    @query.limit = n
    return self
end

#loadObject

Executes the query and fetches the objects; (the next batch if a fetch_window is set).



465
466
467
468
469
470
471
472
473
474
475
# File 'lib/spiderfw/model/query_set.rb', line 465

def load
    return self unless loadable?
    clear
    @loaded = false
    @loaded_elements = {}
    return load_next if @fetch_window && !@query.offset
    mapper.find(@query.clone, self)
    @loaded = true
    @modified = false
    return self
end

#load_next(page = nil) ⇒ Object

Loads the next batch of objects.



492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
# File 'lib/spiderfw/model/query_set.rb', line 492

def load_next(page=nil)
    if (@fetch_window)
        @query.limit = @fetch_window
        if (page)
            @window_current_start = (page - 1) * @fetch_window + 1
        else
            if (!@window_current_start)
                @window_current_start = 1
            else
                @window_current_start += @fetch_window
            end
        end
        @query.offset = @window_current_start-1
    end
    return load
end

#load_to_index(i) ⇒ Object

Loads objects up to index i



485
486
487
488
489
# File 'lib/spiderfw/model/query_set.rb', line 485

def load_to_index(i)
    return load unless @fetch_window
    page = i / @fetch_window + 1
    load_next(page)
end

#loadable?Boolean

Returns:

  • (Boolean)


523
524
525
# File 'lib/spiderfw/model/query_set.rb', line 523

def loadable?
    @loadable
end

#loaded?(index = nil) ⇒ Boolean

If a Fixnum is passed, will tell if the given index is loaded. With no argument, will tell if the QuerySet is loaded

Returns:

  • (Boolean)


511
512
513
514
515
516
# File 'lib/spiderfw/model/query_set.rb', line 511

def loaded?(index=nil)
    return @loaded if !@loaded || !index || !@fetch_window
    return false unless @window_current_start
    return true if index >= @window_current_start-1 && index < @window_current_start+@fetch_window-1
    return false
end

#map_currentObject



685
686
687
688
689
# File 'lib/spiderfw/model/query_set.rb', line 685

def map_current
    a = []
    each_current{ |row| a << yield(row) }
    a
end

#mapperObject

Model mapper.



105
106
107
# File 'lib/spiderfw/model/query_set.rb', line 105

def mapper
    @model.mapper
end

#merge(query_set) ⇒ Object

Merges the content of another QuerySet.



401
402
403
404
# File 'lib/spiderfw/model/query_set.rb', line 401

def merge(query_set)
    @objects += query_set.instance_variable_get(:"@objects")
    reindex
end

#modified?Boolean

Returns:

  • (Boolean)


226
227
228
229
230
231
232
# File 'lib/spiderfw/model/query_set.rb', line 226

def modified?
    return true if @modified
    @objects.each do |obj|
        return true if obj.modified?
    end
    return false
end

#no_autoload(traverse = true) ⇒ Object

Disables autoload. If a block is given, the current autoload value will be restored after yielding.



137
138
139
140
141
142
# File 'lib/spiderfw/model/query_set.rb', line 137

def no_autoload(traverse=true)
    prev_autoload = autoload?
    self.autoload(false, traverse)
    yield
    self.autoload(prev_autoload, traverse)
end

#offset(n) ⇒ Object

Calls #Query.offset



791
792
793
794
# File 'lib/spiderfw/model/query_set.rb', line 791

def offset(n)
    @query.offset = n
    return self
end

#order_by(*elements) ⇒ Object

Calls Query.order_by



440
441
442
443
# File 'lib/spiderfw/model/query_set.rb', line 440

def order_by(*elements)
    @query.order_by *elements
    return self
end

#page(page, rows) ⇒ Object



796
797
798
799
# File 'lib/spiderfw/model/query_set.rb', line 796

def page(page, rows)
    @query.page(page, rows)
    self
end

#pagesObject



801
802
803
804
# File 'lib/spiderfw/model/query_set.rb', line 801

def pages
    return nil unless @query.limit
    (self.total_rows.to_f / @query.limit).ceil
end

#reindexObject

Rebuild object index.



312
313
314
315
316
317
318
319
320
# File 'lib/spiderfw/model/query_set.rb', line 312

def reindex # :nodoc:
    @index_lookup.each_key do |index|
        @index_lookup[index] = {}
    end
    each_current do |obj|
        index_object(obj)
    end
    return self
end

#reject!(&proc) ⇒ Object



702
703
704
# File 'lib/spiderfw/model/query_set.rb', line 702

def reject!(&proc)
    @objects.reject!(&proc)
end

#reverseObject



681
682
683
# File 'lib/spiderfw/model/query_set.rb', line 681

def reverse
    self.to_a.reverse
end

#saveObject

Saves each object in the QuerySet.



528
529
530
# File 'lib/spiderfw/model/query_set.rb', line 528

def save
    no_autoload(false){ each{ |obj| obj.save } }
end

#save!Object



532
533
534
# File 'lib/spiderfw/model/query_set.rb', line 532

def save!
    no_autoload(false){ each{ |obj| obj.save! } }
end

#save_all(params = {}) ⇒ Object

Calls #BaseModel.save_all on each object in the QuerySet.



547
548
549
550
551
552
# File 'lib/spiderfw/model/query_set.rb', line 547

def save_all(params={})
    @objects.each do |obj| 
#                next if (unit_of_work && !unit_of_work.save?(obj))
        obj.save_all(params)
    end
end

#search_key(obj, name) ⇒ Object

FIXME: ???



334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/spiderfw/model/query_set.rb', line 334

def search_key(obj, name) # :nodoc:
    sub = obj.is_a?(Hash) ? obj[name] : obj.get(name.to_sym)
    if (sub.is_a?(Spider::Model::BaseModel))
        name_parts = name.to_s.split('.')
        model = @model
        name_parts.each do |part|
            model = model.elements[part.to_sym].type
        end
        model.primary_keys.map{ |k| sub.get(k).to_s }.join(',')
    else
        sub.to_s
    end
end

#select(&proc) ⇒ Object

Returns a (static) QuerySet of the objects for which the block evaluates to true.



270
271
272
# File 'lib/spiderfw/model/query_set.rb', line 270

def select(&proc)
    return QuerySet.new(@model, select_array(&proc))
end

#select_arrayObject

 Like #select, but returns an array



267
# File 'lib/spiderfw/model/query_set.rb', line 267

alias :select_array :select

#set(element, value) ⇒ Object

Sets the value of an element on all currently loaded objects.



453
454
455
456
457
458
459
460
461
462
# File 'lib/spiderfw/model/query_set.rb', line 453

def set(element, value)
    element_name = element.is_a?(Element) ? element.name : element
    fixed(element_name, value)
#            @query.condition.set(element, '=', value)
    no_autoload(false) do
        each do |obj|
            obj.set(element_name, value)
        end
    end
end

#set_data(data) ⇒ Object

Adds objects to the QuerySet. The argument must be an Enumerable (and should contain BaseModel instances).



145
146
147
148
149
150
151
152
153
154
# File 'lib/spiderfw/model/query_set.rb', line 145

def set_data(data)
    if (data.is_a?(Enumerable))
        data.each do |val|
            self << val
        end
    else
        self << data
    end
    
end

#set_parent(obj, element) ⇒ Object

Sets containing model and element.



131
132
133
134
# File 'lib/spiderfw/model/query_set.rb', line 131

def set_parent(obj, element)
    @_parent = obj
    @_parent_element = element
end

#start_for_index(i) ⇒ Object

Start for the query to get index i



478
479
480
481
482
# File 'lib/spiderfw/model/query_set.rb', line 478

def start_for_index(i) # :nodoc:
    return 1 unless @fetch_window
    page = i / @fetch_window + 1
    return (page - 1) * @fetch_window + 1
end

#tableObject

Prints an ASCII table



603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
# File 'lib/spiderfw/model/query_set.rb', line 603

def table
    
    # Functions for determining terminal size:
    # Copyright (c) 2010 Gabriel Horner, MIT LICENSE
    # http://github.com/cldwalker/hirb.git
    
    # Determines if a shell command exists by searching for it in ENV['PATH'].
    def command_exists?(command)
      ENV['PATH'].split(File::PATH_SEPARATOR).any? {|d| File.exists? File.join(d, command) }
    end

    # Returns [width, height] of terminal when detected, nil if not detected.
    # Think of this as a simpler version of Highline's Highline::SystemExtensions.terminal_size()
    def detect_terminal_size
      if (ENV['COLUMNS'] =~ /^\d+$/) && (ENV['LINES'] =~ /^\d+$/)
        [ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
      elsif (RUBY_PLATFORM =~ /java/ || !STDIN.tty?) && command_exists?('tput')
        [`tput cols`.to_i, `tput lines`.to_i]
      else
        command_exists?('stty') ? `stty size`.scan(/\d+/).map { |s| s.to_i }.reverse : nil
      end
    rescue
      nil
    end
    
    
    return print("Empty\n") if length < 1
    columns = detect_terminal_size[0]
    a = to_flat_array
    m_sizes = Hash.new(0) # one separator column
    a.each do |row|
        row.each do |key, val|
            m_sizes[key] = val.length if val.length > m_sizes[key]
        end
    end
    elements = @model.elements_array.select{ |el| m_sizes[el.name] > 0}
    elements.each do |el|
        m_sizes[el.name] = el.label.length if el.label.length > m_sizes[el.name] + 1
    end
    reduce = columns.to_f/(m_sizes.values.inject{ |sum, s| sum + s })
    sizes = {}
    m_sizes.each_key { |k| sizes[k] = m_sizes[k] * reduce }
    avail = columns - sizes.values.inject{ |sum, s| sum + s }
    while avail > 0 && (truncated = sizes.reject{ |k, v| v < m_sizes[k] }).length > 0
        truncated.each_key do |k|
            break if avail < 1
            sizes[k] += 1; avail -= 1
        end
    end
    sizes.each do |k, v|
        sizes[k] = v.floor
    end
    print "\n"
    1.upto(columns) { print "-" }
    print "\n"
    elements.each do |el|
        print "|"
        print el.label[0..sizes[el.name]-1].ljust(sizes[el.name])
    end
    print "\n"
    1.upto(columns) { print "-" }
    print "\n"
    a.each do |row|
        elements.each do |el|
            print "|"
            print row[el.name][0..sizes[el.name]-1].ljust(sizes[el.name])
        end
        print "\n"
    end
    1.upto(columns) { print "-" }
    print "\n"
    
end

#to_aObject



677
678
679
# File 'lib/spiderfw/model/query_set.rb', line 677

def to_a
    self.map{ |row| row }
end

#to_flat_arrayObject

Returns an array of Hashes, with each value of the object is converted to string.



692
693
694
695
696
697
698
699
700
# File 'lib/spiderfw/model/query_set.rb', line 692

def to_flat_array
    map do |obj|
        h = {}
        obj.class.each_element do |el|
            h[el.name] = obj.element_has_value?(el) ? obj.get(el).to_s : ''
        end
        h
    end
end

#to_hash_arrayObject

Returns an array with the results of calling #BaseModel.to_hash_array on each object.



590
591
592
# File 'lib/spiderfw/model/query_set.rb', line 590

def to_hash_array
    return self.map{ |obj| obj.to_hash }
end

#to_indexed_hash(element) ⇒ Object



594
595
596
597
598
599
600
# File 'lib/spiderfw/model/query_set.rb', line 594

def to_indexed_hash(element)
    hash = {}
    self.each do |row|
        hash[row.get(element)] = row
    end
    hash
end

#to_json(state = nil, &proc) ⇒ Object



574
575
576
577
578
579
580
# File 'lib/spiderfw/model/query_set.rb', line 574

def to_json(state=nil, &proc)
    load unless loaded? || !autoload?
    res =  "[" +
        self.map{ |obj| obj.to_json(&proc) }.join(',') +
        "]"
    return res
end

#to_sObject



710
711
712
# File 'lib/spiderfw/model/query_set.rb', line 710

def to_s
    self.map{ |o| o.to_s }.join(', ')
end

#updateObject

Calls #BaseModel.update on each object in the QuerySet.



542
543
544
# File 'lib/spiderfw/model/query_set.rb', line 542

def update
    no_autoload(false){ each{ |obj| obj.update } }
end

#update_loaded_elementsObject

Checks contained objects’ loaded elements.



212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/spiderfw/model/query_set.rb', line 212

def update_loaded_elements

    return if currently_empty?
    f_loaded = {}
    @loaded_elements = {}
    @loaded_elements.merge!(@objects[0].loaded_elements)
    self.each_current do |obj|
        @loaded_elements.each do |el, val|
            f_loaded[el] = false unless obj.loaded_elements[el]
        end
    end
    @loaded_elements.merge!(f_loaded)
end

#where(*params, &proc) ⇒ Object

Calls #Query.where



779
780
781
782
# File 'lib/spiderfw/model/query_set.rb', line 779

def where(*params, &proc)
    @query.where(*params, &proc)
    return self
end

#with_polymorphsObject



445
446
447
448
449
450
# File 'lib/spiderfw/model/query_set.rb', line 445

def with_polymorphs
    @model.polymorphic_models.each do |model, attributes|
        @query.with_polymorph(model)
    end
    self
end

#with_superclassObject



769
770
771
772
# File 'lib/spiderfw/model/query_set.rb', line 769

def with_superclass
    @query.with_superclass
    return self
end