Class: Spider::Model::QuerySet
- 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
-
#_no_identity_mapper ⇒ bool
If bool, on’t put this queryset’s objects into the IdentityMapper.
-
#_no_parent ⇒ bool
Disables parent setting for this QuerySet.
-
#_parent ⇒ BaseModel
BaseModel instance pointing to this QuerySet.
-
#_parent_element ⇒ Element
Element inside the _parent pointing to this QuerySet.
-
#append_element ⇒ Element
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.
-
#fetch_window ⇒ Fixnum
How many objects to load at a time.
-
#keep_window ⇒ Fixnum
How many objects to keep in memory when advancing the window.
-
#last_query ⇒ Model::Query
Set by mapper.
-
#loadable ⇒ bool
If false, prevents the QuerySet from loading.
-
#loaded ⇒ bool
Whether the QuerySet has been loaded.
-
#loaded_elements ⇒ Hash
readonly
An Hash of autoloaded elements.
-
#model ⇒ Class<BaseModel]
The BaseModel subclass.
-
#modified ⇒ bool
True when the QuerySet has been modified after loading.
-
#objects ⇒ Array
readonly
The actual fetched objects.
-
#query ⇒ Model::Query
The Query.
-
#raw_data ⇒ Hash
readonly
Raw data returned by the mapper, if requested.
-
#total_rows ⇒ Fixnum
Total number of objects that would be returned had the Query no limit.
Class Method Summary collapse
-
.autoloading(model, query_or_val = nil) ⇒ QuerySet
Instantiates an autoloading queryset.
-
.static(model, query_or_val = nil) ⇒ QuerySet
Instantiates a non-autoloading queryset.
Instance Method Summary collapse
-
#+(other) ⇒ QuerySet
Returns a new QuerySet containing objects from both this and the other.
-
#<<(obj, raw = nil) ⇒ void
Adds an object to the set.
-
#[](index) ⇒ BaseModel
Accesses an object.
-
#[]=(index, val) ⇒ void
Sets an object.
-
#all_children(path) ⇒ Array
Given a dotted path, will return an array of all objects reachable by that path Example objectset.all_children(‘friends.collegues.addresses.street_name’).
-
#autoload(value, traverse = true) ⇒ void
Enables or disables autoload; if the second argument is true, will traverse contained objects.
-
#autoload=(bool) ⇒ void
See ##autoload.
-
#autoload? ⇒ bool
True if autoload is enabled, False otherwise.
-
#change_model(model) ⇒ self
Changes the model of the QuerySet; will call BaseModel#become on children.
-
#clear ⇒ void
Remove all elements from self.
-
#clone ⇒ QuerySet
Performs a deep copy.
-
#command_exists?(command) ⇒ Boolean
Determines if a shell command exists by searching for it in ENV.
-
#current_length ⇒ Fixnum
Current number of objects fetched.
-
#currently_empty? ⇒ bool
True if no object has been fetched yet.
-
#cut(*params) ⇒ Array
An array with the results of calling BaseModel#cut on each object.
-
#delete(obj) ⇒ BaseModel|nil
Removes the given object from the QuerySet.
-
#delete_at(index) ⇒ BaseModel|nil
Removes the object at the given index from the QuerySet.
-
#delete_if(&proc) ⇒ nil
Deletes every element for which block evaluates to true.
-
#detect_terminal_size ⇒ Object
Returns [width, height] of terminal when detected, nil if not detected.
-
#each {|BaseModel| ... } ⇒ void
Iterates on objects, loading when needed.
-
#each_current {|BaseModel| ... } ⇒ void
Iterates on currently loaded objects.
-
#each_current_index {|Fixnum| ... } ⇒ void
Iterates on indexes without loading.
-
#each_index {|Fixnum| ... } ⇒ void
Iterates yielding the queryset index.
-
#each_rolling_index {|BaseModel| ... } ⇒ void
Iterates yielding the internal objects index.
-
#element_loaded(element) ⇒ void
Registers that the element has been loaded.
-
#element_loaded?(element) ⇒ bool
True if the element has been loaded from the Storage.
-
#element_queryset(el) ⇒ QuerySet
The QuerySet corresponding to an element in the current QuerySet.
-
#empty! ⇒ void
Removes all objects from the QuerySet.
-
#empty? ⇒ bool
Returns true if the QuerySet has no elements.
-
#find(params) ⇒ QuerySet
Searchs the index for objects matching the given params.
-
#fixed(name, value) ⇒ void
Sets a fixed value: it will be applied to every object.
-
#has_more? ⇒ bool
True if the query had a limit, and more results can be fetched.
-
#identity_mapper ⇒ IdentityMapper
Returns the current QuerySet IdentityMapper instance, or instantiates a new one.
-
#identity_mapper=(im) ⇒ void
Assigns an IdentityMapper to the QuerySet.
-
#include?(val) ⇒ bool
Returns true if the QuerySet includes the given value.
-
#index_by(*elements) ⇒ self
Index objects by some elements.
-
#index_object(obj) ⇒ void
Adds object to the index.
-
#initialize(model, query_or_val = nil) ⇒ QuerySet
constructor
A new instance of QuerySet.
-
#insert ⇒ void
Calls BaseModel#insert on each object in the QuerySet.
-
#inspect ⇒ String
A textual description of the QuerySet.
-
#instantiate_object(val = nil) ⇒ BaseModel
Returns a new instance of @model from val.
-
#last ⇒ BaseModel
The last object in the QuerySet.
-
#length ⇒ Fixnum
Number of objects fetched.
-
#limit(n) ⇒ self
Calls Spider::Model::Query#limit on the query.
-
#load ⇒ self
Executes the query and fetches the objects; (the next batch if a fetch_window is set).
-
#load_next(page = nil) ⇒ self
Loads the next batch of objects.
-
#load_to_index(i) ⇒ void
Loads objects up to index i.
-
#loadable? ⇒ bool
True if the QuerySet can be loaded.
-
#loaded?(index = nil) ⇒ bool
If a Fixnum is passed, will tell if the given index is loaded.
-
#map_current ⇒ Array
Calls map on currently loaded objects.
-
#mapper ⇒ Model::Mapper
The model’s mapper.
-
#merge(query_set) ⇒ void
Merges the content of another QuerySet.
-
#method_missing(method, *args, &proc) ⇒ Object
Missing methods will be sent to the query.
-
#modified? ⇒ true
True if the QuerySet, or any of its children, has been modified since loading.
-
#no_autoload(traverse = true) ⇒ void
Disables autoload.
-
#offset(n) ⇒ self
Calls Spider::Model::Query#offset.
-
#order_by(*elements) ⇒ self
Calls Spider::Model::Query#order_by on the QuerySet’s query.
-
#page(page, rows) ⇒ self
Calls Spider::Model::Query#page on the Query.
-
#pages ⇒ Fixnum|nil
Total number of available pages for current query (or nil if no limit is set).
-
#reindex ⇒ self
Rebuild object index.
-
#reject! {|BaseModel| ... } ⇒ void
Removes the objects for which the block returns true from the QuerySet.
-
#reverse ⇒ Array
A reversed Array.
-
#save ⇒ void
Saves each object in the QuerySet.
-
#save! ⇒ void
Calls BaseModel#save! on each object in the QuerySet.
-
#save_all(params = {}) ⇒ void
Calls BaseModel#save_all on each object in the QuerySet.
-
#search_key(obj, name) ⇒ String
The index key for an object’s element.
-
#select(&proc) ⇒ QuerySet
Returns a (static) QuerySet of the objects for which the block evaluates to true.
-
#select_array ⇒ Array
Like #select, but returns an array.
-
#set(element, value) ⇒ void
Sets the value of an element on all currently loaded objects.
-
#set_data(data) ⇒ void
Adds objects to the QuerySet.
-
#set_parent(obj, element) ⇒ void
Sets containing model and element.
-
#start_for_index(i) ⇒ Fixnum
The index to start with to get the page containing the i-th element.
-
#table ⇒ void
Prints an ASCII table of the QuerySet.
-
#to_a ⇒ Array
The Array corresponding to the QuerySet.
-
#to_flat_array ⇒ Array
Returns an array of Hashes, with each value of the object is converted to string.
-
#to_hash_array ⇒ Array
An array with the results of calling #BaseModel.to_hash_array on each object.
-
#to_indexed_hash(element) ⇒ Hash
A Hash, indexed by the value of element on the object.
-
#to_json(state = nil, &proc) ⇒ String
The JSON representation of the QuerySet.
-
#to_s ⇒ String
All the objects, to_s, joined by ‘, ’.
-
#update ⇒ void
Calls BaseModel#update on each object in the QuerySet.
-
#update_loaded_elements ⇒ void
Ensures children’s loaded_elments match the QuerySet’s ones.
-
#where(*params, &proc) ⇒ self
Calls Spider::Model::Query#where on the query.
-
#with_polymorphs ⇒ self
Calls Query#with_polymorphs on the QuerySet’s query.
-
#with_superclass ⇒ self
Calls Spider::Model::Query#with_superclass on the query.
Constructor Details
#initialize(model, query_or_val = nil) ⇒ QuerySet
Returns a new instance of QuerySet.
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 |
# File 'lib/spiderfw/model/query_set.rb', line 97 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
Missing methods will be sent to the query
868 869 870 871 872 873 874 875 |
# File 'lib/spiderfw/model/query_set.rb', line 868 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_mapper ⇒ bool
If bool, on’t put this queryset’s objects into the IdentityMapper
68 69 70 |
# File 'lib/spiderfw/model/query_set.rb', line 68 def _no_identity_mapper @_no_identity_mapper end |
#_no_parent ⇒ bool
Disables parent setting for this QuerySet
18 19 20 |
# File 'lib/spiderfw/model/query_set.rb', line 18 def _no_parent @_no_parent end |
#_parent ⇒ BaseModel
BaseModel instance pointing to this QuerySet
12 13 14 |
# File 'lib/spiderfw/model/query_set.rb', line 12 def _parent @_parent end |
#_parent_element ⇒ Element
Element inside the _parent pointing to this QuerySet.
15 16 17 |
# File 'lib/spiderfw/model/query_set.rb', line 15 def _parent_element @_parent_element end |
#append_element ⇒ Element
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
62 63 64 |
# File 'lib/spiderfw/model/query_set.rb', line 62 def append_element @append_element end |
#fetch_window ⇒ Fixnum
How many objects to load at a time. If nil, all the objects returned by the Query will be loaded.
46 47 48 |
# File 'lib/spiderfw/model/query_set.rb', line 46 def fetch_window @fetch_window end |
#keep_window ⇒ Fixnum
How many objects to keep in memory when advancing the window. If nil, all objects will be kept.
49 50 51 |
# File 'lib/spiderfw/model/query_set.rb', line 49 def keep_window @keep_window end |
#last_query ⇒ Model::Query
Set by mapper
33 34 35 |
# File 'lib/spiderfw/model/query_set.rb', line 33 def last_query @last_query end |
#loadable ⇒ bool
If false, prevents the QuerySet from loading.
65 66 67 |
# File 'lib/spiderfw/model/query_set.rb', line 65 def loadable @loadable end |
#loaded ⇒ bool
Whether the QuerySet has been loaded
42 43 44 |
# File 'lib/spiderfw/model/query_set.rb', line 42 def loaded @loaded end |
#loaded_elements ⇒ Hash (readonly)
An Hash of autoloaded elements.
24 25 26 |
# File 'lib/spiderfw/model/query_set.rb', line 24 def loaded_elements @loaded_elements end |
#model ⇒ Class<BaseModel]
The BaseModel subclass
36 37 38 |
# File 'lib/spiderfw/model/query_set.rb', line 36 def model @model end |
#modified ⇒ bool
Returns True when the QuerySet has been modified after loading.
70 71 72 |
# File 'lib/spiderfw/model/query_set.rb', line 70 def modified @modified end |
#objects ⇒ Array (readonly)
The actual fetched objects.
27 28 29 |
# File 'lib/spiderfw/model/query_set.rb', line 27 def objects @objects end |
#query ⇒ Model::Query
The Query
30 31 32 |
# File 'lib/spiderfw/model/query_set.rb', line 30 def query @query end |
#raw_data ⇒ Hash (readonly)
Raw data returned by the mapper, if requested.
21 22 23 |
# File 'lib/spiderfw/model/query_set.rb', line 21 def raw_data @raw_data end |
#total_rows ⇒ Fixnum
Total number of objects that would be returned had the Query no limit.
39 40 41 |
# File 'lib/spiderfw/model/query_set.rb', line 39 def total_rows @total_rows end |
Class Method Details
.autoloading(model, query_or_val = nil) ⇒ QuerySet
Instantiates an autoloading queryset
86 87 88 89 90 |
# File 'lib/spiderfw/model/query_set.rb', line 86 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) ⇒ QuerySet
Instantiates a non-autoloading queryset
76 77 78 79 80 |
# File 'lib/spiderfw/model/query_set.rb', line 76 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) ⇒ QuerySet
Returns a new QuerySet containing objects from both this and the other.
319 320 321 322 323 324 325 |
# File 'lib/spiderfw/model/query_set.rb', line 319 def +(other) qs = self.clone other.each do |obj| qs << obj end return qs end |
#<<(obj, raw = nil) ⇒ void
This method returns an undefined value.
Adds an object to the set. Also stores the raw data if it is passed as the second parameter.
214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/spiderfw/model/query_set.rb', line 214 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) ⇒ BaseModel
Accesses an object. Data will be loaded according to fetch_window.
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/spiderfw/model/query_set.rb', line 232 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) ⇒ void
This method returns an undefined value.
Sets an object
254 255 256 257 258 259 260 261 262 263 |
# File 'lib/spiderfw/model/query_set.rb', line 254 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) ⇒ Array
Given a dotted path, will return an array of all objects reachable by that path Example
objectset.all_children('friends.collegues.addresses.street_name')
896 897 898 899 900 901 902 |
# File 'lib/spiderfw/model/query_set.rb', line 896 def all_children(path) if (path.length > 0) children = @objects.map{ |obj| obj.all_children(path.clone) }.flatten else return @objects end end |
#autoload(value, traverse = true) ⇒ void
This method returns an undefined value.
Enables or disables autoload; if the second argument is true, will traverse contained objects.
148 149 150 151 |
# File 'lib/spiderfw/model/query_set.rb', line 148 def autoload(value, traverse=true) @autoload = value @objects.each{ |obj| obj.autoload = value } if traverse end |
#autoload=(bool) ⇒ void
This method returns an undefined value.
See ##autoload
156 157 158 |
# File 'lib/spiderfw/model/query_set.rb', line 156 def autoload=(bool) autoload(bool) end |
#autoload? ⇒ bool
Returns True if autoload is enabled, False otherwise.
161 162 163 |
# File 'lib/spiderfw/model/query_set.rb', line 161 def autoload? @autoload ? true : false end |
#change_model(model) ⇒ self
Changes the model of the QuerySet; will call BaseModel#become on children.
202 203 204 205 206 207 208 |
# File 'lib/spiderfw/model/query_set.rb', line 202 def change_model(model) @model = model @objects.each_index do |i| @objects[i] = @objects[i].become(model) end return self end |
#clear ⇒ void
This method returns an undefined value.
Remove all elements from self
436 437 438 439 |
# File 'lib/spiderfw/model/query_set.rb', line 436 def clear @objects = [] @index_lookup.each_key{ |k| @index_lookup[k] = {} } end |
#clone ⇒ QuerySet
Performs a deep copy
984 985 986 987 988 989 990 991 992 |
# File 'lib/spiderfw/model/query_set.rb', line 984 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.
753 754 755 |
# File 'lib/spiderfw/model/query_set.rb', line 753 def command_exists?(command) ENV['PATH'].split(File::PATH_SEPARATOR).any? {|d| File.exists? File.join(d, command) } end |
#current_length ⇒ Fixnum
Current number of objects fetched.
364 365 366 |
# File 'lib/spiderfw/model/query_set.rb', line 364 def current_length @objects.length end |
#currently_empty? ⇒ bool
Returns True if no object has been fetched yet.
376 377 378 |
# File 'lib/spiderfw/model/query_set.rb', line 376 def currently_empty? @objects.empty? end |
#cut(*params) ⇒ Array
Returns An array with the results of calling BaseModel#cut on each object.
724 725 726 727 |
# File 'lib/spiderfw/model/query_set.rb', line 724 def cut(*params) load unless loaded? || !autoload? return self.map{ |obj| obj.cut(*params) } end |
#delete(obj) ⇒ BaseModel|nil
Removes the given object from the QuerySet
312 313 314 |
# File 'lib/spiderfw/model/query_set.rb', line 312 def delete(obj) @objects.delete(obj) end |
#delete_at(index) ⇒ BaseModel|nil
Removes the object at the given index from the QuerySet
299 300 301 |
# File 'lib/spiderfw/model/query_set.rb', line 299 def delete_at(index) @objects.delete_at(index) end |
#delete_if(&proc) ⇒ nil
Deletes every element for which block evaluates to true
305 306 307 |
# File 'lib/spiderfw/model/query_set.rb', line 305 def delete_if(&proc) @objects.delete_if(&proc) end |
#detect_terminal_size ⇒ Object
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()
759 760 761 762 763 764 765 766 767 768 769 |
# File 'lib/spiderfw/model/query_set.rb', line 759 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 |
#each {|BaseModel| ... } ⇒ void
This method returns an undefined value.
Iterates on objects, loading when needed.
451 452 453 454 455 456 457 458 459 460 |
# File 'lib/spiderfw/model/query_set.rb', line 451 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_current {|BaseModel| ... } ⇒ void
This method returns an undefined value.
Iterates on currently loaded objects
444 445 446 |
# File 'lib/spiderfw/model/query_set.rb', line 444 def each_current @objects.each { |obj| yield obj } end |
#each_current_index {|Fixnum| ... } ⇒ void
This method returns an undefined value.
Iterates on indexes without loading.
490 491 492 493 494 495 |
# File 'lib/spiderfw/model/query_set.rb', line 490 def each_current_index @objects.each_index do |i| i += @window_current_start-1 if @window_current_start yield i end end |
#each_index {|Fixnum| ... } ⇒ void
This method returns an undefined value.
Iterates yielding the queryset index. Will load when needed.
480 481 482 483 484 485 |
# File 'lib/spiderfw/model/query_set.rb', line 480 def each_index self.each_rolling_index do |i| i += @window_current_start-1 if @window_current_start yield i end end |
#each_rolling_index {|BaseModel| ... } ⇒ void
This method returns an undefined value.
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.
466 467 468 469 470 471 472 473 474 475 |
# File 'lib/spiderfw/model/query_set.rb', line 466 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) ⇒ void
This method returns an undefined value.
Registers that the element has been loaded.
907 908 909 910 |
# File 'lib/spiderfw/model/query_set.rb', line 907 def element_loaded(element) element = element.name if element.is_a?(Element) @loaded_elements[element] = true end |
#element_loaded?(element) ⇒ bool
Returns True if the element has been loaded from the Storage.
914 915 916 917 |
# File 'lib/spiderfw/model/query_set.rb', line 914 def element_loaded?(element) element = element.name if element.is_a?(Element) @loaded_elements[element] end |
#element_queryset(el) ⇒ QuerySet
Returns The QuerySet corresponding to an element in the current QuerySet.
879 880 881 882 883 884 885 886 887 888 889 |
# File 'lib/spiderfw/model/query_set.rb', line 879 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! ⇒ void
This method returns an undefined value.
Removes all objects from the QuerySet
858 859 860 |
# File 'lib/spiderfw/model/query_set.rb', line 858 def empty! @objects = [] end |
#empty? ⇒ bool
Returns true if the QuerySet has no elements. Will load if the QuerySet is autoloading.
370 371 372 373 |
# File 'lib/spiderfw/model/query_set.rb', line 370 def empty? load unless @loaded || !autoload? @objects.empty? end |
#find(params) ⇒ QuerySet
Searchs the index for objects matching the given params.
537 538 539 540 541 542 543 544 545 546 547 |
# File 'lib/spiderfw/model/query_set.rb', line 537 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) ⇒ void
This method returns an undefined value.
Sets a fixed value: it will be applied to every object.
139 140 141 |
# File 'lib/spiderfw/model/query_set.rb', line 139 def fixed(name, value) @fixed[name] = value end |
#has_more? ⇒ bool
True if the query had a limit, and more results can be fetched.
349 350 351 352 353 354 |
# File 'lib/spiderfw/model/query_set.rb', line 349 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_mapper ⇒ IdentityMapper
Returns the current QuerySet IdentityMapper instance, or instantiates a new one
921 922 923 924 |
# File 'lib/spiderfw/model/query_set.rb', line 921 def identity_mapper return Spider::Model.identity_mapper if Spider::Model.identity_mapper @identity_mapper ||= IdentityMapper.new end |
#identity_mapper=(im) ⇒ void
This method returns an undefined value.
Assigns an IdentityMapper to the QuerySet
929 930 931 |
# File 'lib/spiderfw/model/query_set.rb', line 929 def identity_mapper=(im) @identity_mapper = im end |
#include?(val) ⇒ bool
Returns true if the QuerySet includes the given value.
The value can be a BaseModel, which will be searched as it is;
a Hash, in which case an Object with all the given values will be searched;
or an Object, which will be searched as the (only) primary key of a contained model
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 |
# File 'lib/spiderfw/model/query_set.rb', line 514 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) ⇒ self
Index objects by some elements.
383 384 385 386 387 388 389 |
# File 'lib/spiderfw/model/query_set.rb', line 383 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) ⇒ void
This method returns an undefined value.
Adds object to the index
407 408 409 410 411 412 413 414 415 |
# File 'lib/spiderfw/model/query_set.rb', line 407 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 |
#insert ⇒ void
This method returns an undefined value.
Calls BaseModel#insert on each object in the QuerySet.
670 671 672 |
# File 'lib/spiderfw/model/query_set.rb', line 670 def insert no_autoload(false){ each{ |obj| obj.insert } } end |
#inspect ⇒ String
Returns A textual description of the QuerySet.
708 709 710 |
# File 'lib/spiderfw/model/query_set.rb', line 708 def inspect return "#{self.class.name}:\n@model=#{@model}, @query=#{query.inspect}, @objects=#{@objects.inspect}" end |
#instantiate_object(val = nil) ⇒ BaseModel
Returns a new instance of @model from val.
692 693 694 695 696 697 698 699 700 701 702 703 704 705 |
# File 'lib/spiderfw/model/query_set.rb', line 692 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 |
#last ⇒ BaseModel
Returns The last object in the QuerySet.
291 292 293 294 |
# File 'lib/spiderfw/model/query_set.rb', line 291 def last load unless (@loaded || !autoload?) && loaded?(total_rows-1) @objects.last end |
#length ⇒ Fixnum
Number of objects fetched. Will call load if not loaded yet. Note: this is not the total number of objects responding to the Query; it may be equal to the fetch_window, or to the @query.limit.
331 332 333 334 |
# File 'lib/spiderfw/model/query_set.rb', line 331 def length load unless @loaded || !autoload? @objects.length end |
#limit(n) ⇒ self
Calls Spider::Model::Query#limit on the query
953 954 955 956 |
# File 'lib/spiderfw/model/query_set.rb', line 953 def limit(n) @query.limit = n return self end |
#load ⇒ self
Executes the query and fetches the objects; (the next batch if a fetch_window is set).
583 584 585 586 587 588 589 590 591 592 593 |
# File 'lib/spiderfw/model/query_set.rb', line 583 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) ⇒ self
Loads the next batch of objects.
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 |
# File 'lib/spiderfw/model/query_set.rb', line 615 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) ⇒ void
This method returns an undefined value.
Loads objects up to index i
606 607 608 609 610 |
# File 'lib/spiderfw/model/query_set.rb', line 606 def load_to_index(i) return load unless @fetch_window page = i / @fetch_window + 1 load_next(page) end |
#loadable? ⇒ bool
Returns True if the QuerySet can be loaded.
652 653 654 |
# File 'lib/spiderfw/model/query_set.rb', line 652 def loadable? @loadable end |
#loaded?(index = nil) ⇒ bool
If a Fixnum is passed, will tell if the given index is loaded. With no argument, will tell if the QuerySet is fully loaded
636 637 638 639 640 641 |
# File 'lib/spiderfw/model/query_set.rb', line 636 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_current ⇒ Array
Returns Calls map on currently loaded objects.
831 832 833 834 835 |
# File 'lib/spiderfw/model/query_set.rb', line 831 def map_current a = [] each_current{ |row| a << yield(row) } a end |
#mapper ⇒ Model::Mapper
Returns The model’s mapper.
131 132 133 |
# File 'lib/spiderfw/model/query_set.rb', line 131 def mapper @model.mapper end |
#merge(query_set) ⇒ void
This method returns an undefined value.
Merges the content of another QuerySet.
500 501 502 503 |
# File 'lib/spiderfw/model/query_set.rb', line 500 def merge(query_set) @objects += query_set.instance_variable_get(:"@objects") reindex end |
#modified? ⇒ true
Returns True if the QuerySet, or any of its children, has been modified since loading.
282 283 284 285 286 287 288 |
# File 'lib/spiderfw/model/query_set.rb', line 282 def modified? return true if @modified @objects.each do |obj| return true if obj.modified? end return false end |
#no_autoload(traverse = true) ⇒ void
This method returns an undefined value.
Disables autoload. If a block is given, the current autoload value will be restored after yielding.
177 178 179 180 181 182 |
# File 'lib/spiderfw/model/query_set.rb', line 177 def no_autoload(traverse=true) prev_autoload = autoload? self.autoload(false, traverse) yield self.autoload(prev_autoload, traverse) end |
#offset(n) ⇒ self
960 961 962 963 |
# File 'lib/spiderfw/model/query_set.rb', line 960 def offset(n) @query.offset = n return self end |
#order_by(*elements) ⇒ self
Calls Spider::Model::Query#order_by on the QuerySet’s query
552 553 554 555 |
# File 'lib/spiderfw/model/query_set.rb', line 552 def order_by(*elements) @query.order_by(*elements) return self end |
#page(page, rows) ⇒ self
Calls Spider::Model::Query#page on the Query
967 968 969 970 |
# File 'lib/spiderfw/model/query_set.rb', line 967 def page(page, rows) @query.page(page, rows) self end |
#pages ⇒ Fixnum|nil
Returns Total number of available pages for current query (or nil if no limit is set).
973 974 975 976 |
# File 'lib/spiderfw/model/query_set.rb', line 973 def pages return nil unless @query.limit (self.total_rows.to_f / @query.limit).ceil end |
#reindex ⇒ self
Rebuild object index.
394 395 396 397 398 399 400 401 402 |
# File 'lib/spiderfw/model/query_set.rb', line 394 def reindex @index_lookup.each_key do |index| @index_lookup[index] = {} end each_current do |obj| index_object(obj) end return self end |
#reject! {|BaseModel| ... } ⇒ void
This method returns an undefined value.
Removes the objects for which the block returns true from the QuerySet
852 853 854 |
# File 'lib/spiderfw/model/query_set.rb', line 852 def reject!(&proc) @objects.reject!(&proc) end |
#reverse ⇒ Array
Returns A reversed Array.
826 827 828 |
# File 'lib/spiderfw/model/query_set.rb', line 826 def reverse self.to_a.reverse end |
#save ⇒ void
This method returns an undefined value.
Saves each object in the QuerySet.
658 659 660 |
# File 'lib/spiderfw/model/query_set.rb', line 658 def save no_autoload(false){ each{ |obj| obj.save } } end |
#save! ⇒ void
This method returns an undefined value.
Calls BaseModel#save! on each object in the QuerySet.
664 665 666 |
# File 'lib/spiderfw/model/query_set.rb', line 664 def save! no_autoload(false){ each{ |obj| obj.save! } } end |
#save_all(params = {}) ⇒ void
This method returns an undefined value.
Calls BaseModel#save_all on each object in the QuerySet.
682 683 684 685 686 687 |
# File 'lib/spiderfw/model/query_set.rb', line 682 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) ⇒ String
Returns The index key for an object’s element.
420 421 422 423 424 425 426 427 428 429 430 431 432 |
# File 'lib/spiderfw/model/query_set.rb', line 420 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) ⇒ QuerySet
Returns a (static) QuerySet of the objects for which the block evaluates to true.
343 344 345 |
# File 'lib/spiderfw/model/query_set.rb', line 343 def select(&proc) return QuerySet.new(@model, select_array(&proc)) end |
#select_array ⇒ Array
Like #select, but returns an array
338 |
# File 'lib/spiderfw/model/query_set.rb', line 338 alias :select_array :select |
#set(element, value) ⇒ void
This method returns an undefined value.
Sets the value of an element on all currently loaded objects.
570 571 572 573 574 575 576 577 578 579 |
# File 'lib/spiderfw/model/query_set.rb', line 570 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) ⇒ void
This method returns an undefined value.
Adds objects to the QuerySet
188 189 190 191 192 193 194 195 196 197 |
# File 'lib/spiderfw/model/query_set.rb', line 188 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) ⇒ void
This method returns an undefined value.
Sets containing model and element.
169 170 171 172 |
# File 'lib/spiderfw/model/query_set.rb', line 169 def set_parent(obj, element) @_parent = obj @_parent_element = element end |
#start_for_index(i) ⇒ Fixnum
Returns The index to start with to get the page containing the i-th element.
597 598 599 600 601 |
# File 'lib/spiderfw/model/query_set.rb', line 597 def start_for_index(i) # :nodoc: return 1 unless @fetch_window page = i / @fetch_window + 1 return (page - 1) * @fetch_window + 1 end |
#table ⇒ void
This method returns an undefined value.
Prints an ASCII table of the QuerySet
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 |
# File 'lib/spiderfw/model/query_set.rb', line 746 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_a ⇒ Array
Returns The Array corresponding to the QuerySet.
821 822 823 |
# File 'lib/spiderfw/model/query_set.rb', line 821 def to_a self.map{ |row| row } end |
#to_flat_array ⇒ Array
Returns an array of Hashes, with each value of the object is converted to string.
839 840 841 842 843 844 845 846 847 |
# File 'lib/spiderfw/model/query_set.rb', line 839 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_array ⇒ Array
Returns An array with the results of calling #BaseModel.to_hash_array on each object.
730 731 732 |
# File 'lib/spiderfw/model/query_set.rb', line 730 def to_hash_array return self.map{ |obj| obj.to_hash } end |
#to_indexed_hash(element) ⇒ Hash
Returns A Hash, indexed by the value of element on the object.
736 737 738 739 740 741 742 |
# File 'lib/spiderfw/model/query_set.rb', line 736 def to_indexed_hash(element) hash = {} self.each do |row| hash[row.get(element)] = row end hash end |
#to_json(state = nil, &proc) ⇒ String
Returns The JSON representation of the QuerySet.
713 714 715 716 717 718 719 |
# File 'lib/spiderfw/model/query_set.rb', line 713 def to_json(state=nil, &proc) load unless loaded? || !autoload? res = "[" + self.map{ |obj| obj.to_json(&proc) }.join(',') + "]" return res end |
#to_s ⇒ String
Returns All the objects, to_s, joined by ‘, ’.
863 864 865 |
# File 'lib/spiderfw/model/query_set.rb', line 863 def to_s self.map{ |o| o.to_s }.join(', ') end |
#update ⇒ void
This method returns an undefined value.
Calls BaseModel#update on each object in the QuerySet.
676 677 678 |
# File 'lib/spiderfw/model/query_set.rb', line 676 def update no_autoload(false){ each{ |obj| obj.update } } end |
#update_loaded_elements ⇒ void
This method returns an undefined value.
Ensures children’s loaded_elments match the QuerySet’s ones.
267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/spiderfw/model/query_set.rb', line 267 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) ⇒ self
Calls Spider::Model::Query#where on the query.
946 947 948 949 |
# File 'lib/spiderfw/model/query_set.rb', line 946 def where(*params, &proc) @query.where(*params, &proc) return self end |
#with_polymorphs ⇒ self
Calls Query#with_polymorphs on the QuerySet’s query
559 560 561 562 563 564 |
# File 'lib/spiderfw/model/query_set.rb', line 559 def with_polymorphs @model.polymorphic_models.each do |model, attributes| @query.with_polymorph(model) end self end |
#with_superclass ⇒ self
Calls Spider::Model::Query#with_superclass on the query.
935 936 937 938 |
# File 'lib/spiderfw/model/query_set.rb', line 935 def with_superclass @query.with_superclass return self end |