spiderfw 0.6.23 → 0.6.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +10 -1
- data/README.rdoc +1 -1
- data/VERSION +1 -1
- data/apps/config_editor/_init.rb +1 -2
- data/apps/config_editor/controllers/config_editor_controller.rb +1 -7
- data/apps/core/admin/controllers/admin_controller.rb +1 -1
- data/apps/core/admin/public/css/sass/admin.css +35 -31
- data/apps/core/admin/public/sass/admin.scss +6 -1
- data/apps/core/components/widgets/crud/crud.shtml +2 -2
- data/apps/core/components/widgets/table/table.rb +5 -5
- data/apps/core/forms/tags/element_row.erb +15 -10
- data/apps/core/forms/widgets/form/form.rb +35 -22
- data/apps/core/forms/widgets/inputs/checkbox/checkbox.shtml +2 -2
- data/apps/core/forms/widgets/inputs/date_time/date_time.shtml +2 -2
- data/apps/core/forms/widgets/inputs/file_input/file_input.shtml +2 -2
- data/apps/core/forms/widgets/inputs/html_area/html_area.shtml +2 -2
- data/apps/core/forms/widgets/inputs/input/input.shtml +2 -2
- data/apps/core/forms/widgets/inputs/password/password.shtml +2 -2
- data/apps/core/forms/widgets/inputs/search_select/search_select.shtml +1 -1
- data/apps/core/forms/widgets/inputs/select/select.shtml +2 -2
- data/apps/core/forms/widgets/inputs/text/text.shtml +2 -2
- data/apps/core/forms/widgets/inputs/text_area/text_area.shtml +2 -2
- data/apps/core/forms/widgets/inputs/time_span/time_span.shtml +1 -1
- data/blueprints/home/config.ru +8 -0
- data/lib/spiderfw/app.rb +416 -224
- data/lib/spiderfw/cmd/commands/app.rb +243 -239
- data/lib/spiderfw/cmd/commands/cert.rb +421 -417
- data/lib/spiderfw/cmd/commands/config.rb +85 -82
- data/lib/spiderfw/cmd/commands/console.rb +64 -40
- data/lib/spiderfw/cmd/commands/content.rb +29 -25
- data/lib/spiderfw/cmd/commands/create.rb +58 -54
- data/lib/spiderfw/cmd/commands/model.rb +118 -114
- data/lib/spiderfw/cmd/commands/setup.rb +55 -51
- data/lib/spiderfw/cmd/commands/test.rb +63 -59
- data/lib/spiderfw/cmd/commands/webserver.rb +56 -51
- data/lib/spiderfw/config/options/spider.rb +4 -3
- data/lib/spiderfw/controller/controller.rb +2 -0
- data/lib/spiderfw/controller/http_controller.rb +1 -2
- data/lib/spiderfw/controller/mixins/static_content.rb +3 -3
- data/lib/spiderfw/controller/mixins/visual.rb +30 -15
- data/lib/spiderfw/controller/response.rb +84 -0
- data/lib/spiderfw/controller/session/file_session.rb +2 -2
- data/lib/spiderfw/http/adapters/rack.rb +12 -13
- data/lib/spiderfw/http/server.rb +80 -46
- data/lib/spiderfw/i18n/cldr.rb +6 -9
- data/lib/spiderfw/model/base_model.rb +103 -23
- data/lib/spiderfw/model/condition.rb +110 -25
- data/lib/spiderfw/model/mappers/db_mapper.rb +14 -6
- data/lib/spiderfw/model/mappers/mapper.rb +440 -197
- data/lib/spiderfw/model/model.rb +105 -21
- data/lib/spiderfw/model/model_hash.rb +9 -1
- data/lib/spiderfw/model/query.rb +50 -9
- data/lib/spiderfw/model/query_set.rb +211 -44
- data/lib/spiderfw/model/request.rb +28 -21
- data/lib/spiderfw/model/storage/base_storage.rb +125 -10
- data/lib/spiderfw/model/storage/db/db_storage.rb +7 -4
- data/lib/spiderfw/model/storage.rb +8 -1
- data/lib/spiderfw/setup/spider_setup_wizard.rb +9 -7
- data/lib/spiderfw/spider.rb +270 -43
- data/lib/spiderfw/templates/layout.rb +9 -4
- data/lib/spiderfw/templates/resources/sass.rb +3 -2
- data/lib/spiderfw/templates/template.rb +1 -0
- data/lib/spiderfw/utils/annotations.rb +3 -1
- data/lib/spiderfw/utils/logger.rb +1 -1
- data/lib/spiderfw/utils/monkey/symbol.rb +4 -2
- data/lib/spiderfw/utils/shared_store/file_shared_store.rb +2 -2
- data/lib/spiderfw/utils/thread_out.rb +3 -1
- data/public/css/error_page.css +83 -0
- data/public/js/error_page.js +5 -0
- data/spider.gemspec +4 -1
- data/templates/email/error.erb +9 -0
- metadata +28 -12
- data/apps/config_editor/widgets/edit_bool/edit_bool.rb +0 -8
- data/apps/config_editor/widgets/edit_bool/edit_bool.shtml +0 -5
@@ -2,37 +2,50 @@ module Spider; module Model
|
|
2
2
|
|
3
3
|
# The QuerySet expresses represents a Query applied on a Model.
|
4
4
|
# It includes Enumerable, and can be accessed as an Array; but, the QuerySet is lazy, and the actual data will be
|
5
|
-
# fetched only when actually requested, or when a #load is issued.
|
6
|
-
# How much data is fetched and kept in memory can be controlled by setting the #fetch_window
|
7
|
-
# and the #keep_window.
|
5
|
+
# fetched only when actually requested, or when a {#load} is issued.
|
6
|
+
# How much data is fetched and kept in memory can be controlled by setting the {#fetch_window}
|
7
|
+
# and the {#keep_window}.
|
8
8
|
class QuerySet
|
9
9
|
include Enumerable
|
10
10
|
# BaseModel instance pointing to this QuerySet
|
11
|
+
# @return [BaseModel]
|
11
12
|
attr_accessor :_parent
|
12
13
|
# Element inside the _parent pointing to this QuerySet.
|
14
|
+
# @return [Element]
|
13
15
|
attr_accessor :_parent_element
|
14
16
|
# Disables parent setting for this QuerySet
|
17
|
+
# @return [bool]
|
15
18
|
attr_accessor :_no_parent
|
16
19
|
# Raw data returned by the mapper, if requested.
|
20
|
+
# @return [Hash]
|
17
21
|
attr_reader :raw_data
|
18
22
|
# An Hash of autoloaded elements.
|
23
|
+
# @return [Hash]
|
19
24
|
attr_reader :loaded_elements
|
20
25
|
# The actual fetched objects.
|
26
|
+
# @return [Array]
|
21
27
|
attr_reader :objects
|
22
28
|
# The Query
|
29
|
+
# @return [Model::Query]
|
23
30
|
attr_accessor :query
|
24
31
|
# Set by mapper
|
32
|
+
# @return [Model::Query]
|
25
33
|
attr_accessor :last_query # :nodoc: TODO: remove?
|
26
|
-
# The BaseModel
|
34
|
+
# The BaseModel subclass
|
35
|
+
# @return [Class<BaseModel]
|
27
36
|
attr_accessor :model
|
28
37
|
# Total number of objects present in the Storage for the Query
|
38
|
+
# @return [Fixnum]
|
29
39
|
attr_accessor :total_rows
|
30
|
-
#
|
40
|
+
# Whether the QuerySet has been loaded
|
41
|
+
# @return [bool]
|
31
42
|
attr_reader :loaded
|
32
|
-
#
|
43
|
+
# How many objects to load at a time. If nil, all the objects returned by the Query
|
33
44
|
# will be loaded.
|
45
|
+
# @return [Fixnum]
|
34
46
|
attr_accessor :fetch_window
|
35
|
-
#
|
47
|
+
# How many objects to keep in memory when advancing the window. If nil, all objects will be kept.
|
48
|
+
# @return [Fixnum]
|
36
49
|
attr_accessor :keep_window
|
37
50
|
# If something that can't be converted to a @model instance is appended to the QuerySet,
|
38
51
|
# and append_element is set, the appended value will be set on the element named append_element
|
@@ -45,29 +58,42 @@ module Spider; module Model
|
|
45
58
|
# cat.friends << friend
|
46
59
|
# # since the junction was created setting append_element = :other_animal, one can do
|
47
60
|
# cat.friends << lion
|
61
|
+
# @return [Element]
|
48
62
|
attr_accessor :append_element
|
49
|
-
#
|
50
|
-
|
51
|
-
|
63
|
+
# If false, prevents the QuerySet from loading.
|
64
|
+
# @return [bool]
|
65
|
+
attr_accessor :loadable
|
66
|
+
# If bool, on't put this queryset's objects into the IdentityMapper
|
67
|
+
# @return [bool]
|
52
68
|
attr_accessor :_no_identity_mapper
|
69
|
+
# @return [bool] True when the QuerySet has been modified after loading
|
53
70
|
attr_accessor :modified
|
54
71
|
|
55
72
|
# Instantiates a non-autoloading queryset
|
73
|
+
# @param [Class<BaseModel] model
|
74
|
+
# @param [Query|Object] query_or_val see {QuerySet.new}
|
75
|
+
# @return [QuerySet]
|
56
76
|
def self.static(model, query_or_val=nil)
|
57
77
|
qs = self.new(model, query_or_val)
|
58
78
|
qs.autoload = false
|
59
79
|
return qs
|
60
80
|
end
|
61
81
|
|
82
|
+
# Instantiates an autoloading queryset
|
83
|
+
# @param [Class<BaseModel] model
|
84
|
+
# @param [Query|Object] query_or_val see {QuerySet.new}
|
85
|
+
# @return [QuerySet]
|
62
86
|
def self.autoloading(model, query_or_val=nil)
|
63
87
|
qs = self.new(model, query_or_val)
|
64
88
|
qs.autoload = true
|
65
89
|
return qs
|
66
90
|
end
|
67
91
|
|
68
|
-
#
|
69
|
-
#
|
70
|
-
# the QuerySet will
|
92
|
+
# @param [Class<BaseModel] model The BaseModel subclass
|
93
|
+
# @param [Query|Array|BaseModel] query_or_val Can be a Query, or data.
|
94
|
+
# * If a Query is given, the QuerySet will autoload using Query.
|
95
|
+
# * If data is given, the QuerySet will be static (not autoloading),
|
96
|
+
# and the data will be passed to {#set_data}.
|
71
97
|
def initialize(model, query_or_val=nil)
|
72
98
|
@model = model
|
73
99
|
model.extend_queryset(self)
|
@@ -101,39 +127,53 @@ module Spider; module Model
|
|
101
127
|
end
|
102
128
|
|
103
129
|
|
104
|
-
# Model mapper
|
130
|
+
# @return [Model::Mapper] The model's mapper
|
105
131
|
def mapper
|
106
132
|
@model.mapper
|
107
133
|
end
|
108
134
|
|
109
135
|
# Sets a fixed value: it will be applied to every object.
|
136
|
+
# @param [Symbol] name
|
137
|
+
# @param [Object] value
|
138
|
+
# @return [void]
|
110
139
|
def fixed(name, value)
|
111
140
|
@fixed[name] = value
|
112
141
|
end
|
113
142
|
|
114
143
|
# Enables or disables autoload; if the second argument is true, will traverse
|
115
144
|
# contained objects.
|
116
|
-
|
117
|
-
|
118
|
-
|
145
|
+
# @param [bool] value Enable or disable autoload
|
146
|
+
# @param [bool] traverse If true, set autoload to value on contained objects as well
|
147
|
+
# @return [void]
|
148
|
+
def autoload(value, traverse=true)
|
149
|
+
@autoload = value
|
150
|
+
@objects.each{ |obj| obj.autoload = value } if traverse
|
119
151
|
end
|
120
152
|
|
121
|
-
#
|
153
|
+
# See #{#autoload}
|
154
|
+
# @param [bool] value
|
155
|
+
# @return [void]
|
122
156
|
def autoload=(bool)
|
123
157
|
autoload(bool)
|
124
158
|
end
|
125
159
|
|
160
|
+
# @return [bool] True if autoload is enabled, False otherwise
|
126
161
|
def autoload?
|
127
162
|
@autoload ? true : false
|
128
163
|
end
|
129
164
|
|
130
165
|
# Sets containing model and element.
|
166
|
+
# @param [BaseModel] obj
|
167
|
+
# @param [Symbol] element Name of the element inside the parent which points to this QuerySet
|
168
|
+
# @return [void]
|
131
169
|
def set_parent(obj, element)
|
132
170
|
@_parent = obj
|
133
171
|
@_parent_element = element
|
134
172
|
end
|
135
173
|
|
136
174
|
# Disables autoload. If a block is given, the current autoload value will be restored after yielding.
|
175
|
+
# @param [bool] traverse If true, apply to children as well
|
176
|
+
# @return [void]
|
137
177
|
def no_autoload(traverse=true)
|
138
178
|
prev_autoload = autoload?
|
139
179
|
self.autoload(false, traverse)
|
@@ -141,7 +181,10 @@ module Spider; module Model
|
|
141
181
|
self.autoload(prev_autoload, traverse)
|
142
182
|
end
|
143
183
|
|
144
|
-
# Adds objects to the QuerySet
|
184
|
+
# Adds objects to the QuerySet
|
185
|
+
# @param [Enumerable|Object] data If the argument is an Enumerable, its contents will be appendend to the QuerySet;
|
186
|
+
# otherwise, the object will be appended.
|
187
|
+
# @return [void]
|
145
188
|
def set_data(data)
|
146
189
|
if (data.is_a?(Enumerable))
|
147
190
|
data.each do |val|
|
@@ -153,6 +196,9 @@ module Spider; module Model
|
|
153
196
|
|
154
197
|
end
|
155
198
|
|
199
|
+
# Changes the model of the QuerySet; will call {BaseModel#become} on children.
|
200
|
+
# @param [Class<BaseModel] model The model to change to
|
201
|
+
# @return [self]
|
156
202
|
def change_model(model)
|
157
203
|
@model = model
|
158
204
|
@objects.each_index do |i|
|
@@ -162,6 +208,9 @@ module Spider; module Model
|
|
162
208
|
end
|
163
209
|
|
164
210
|
# Adds an object to the set. Also stores the raw data if it is passed as the second parameter.
|
211
|
+
# @param [BaseModel] obj The object to add
|
212
|
+
# @param [Hash] raw Optional raw data associated to the object
|
213
|
+
# @return [void]
|
165
214
|
def <<(obj, raw=nil)
|
166
215
|
return merge(obj) if (obj.class == QuerySet)
|
167
216
|
unless (obj.is_a?(@model))
|
@@ -178,6 +227,8 @@ module Spider; module Model
|
|
178
227
|
|
179
228
|
|
180
229
|
# Accesses an object. Data will be loaded according to fetch_window.
|
230
|
+
# @param [Fixnum] index
|
231
|
+
# @return [BaseModel]
|
181
232
|
def [](index)
|
182
233
|
if (index.is_a?(Range))
|
183
234
|
return index.map{ |i| self[i] }
|
@@ -196,7 +247,10 @@ module Spider; module Model
|
|
196
247
|
return val
|
197
248
|
end
|
198
249
|
|
199
|
-
# Sets an object
|
250
|
+
# Sets an object
|
251
|
+
# @param [Fixnum] index
|
252
|
+
# @param [BaseModel] val
|
253
|
+
# @return [void]
|
200
254
|
def []=(index, val)
|
201
255
|
#load_to_index(index) unless loaded?(index) || !autoload?
|
202
256
|
val = instantiate_object(val) unless val.is_a?(@model)
|
@@ -208,7 +262,8 @@ module Spider; module Model
|
|
208
262
|
@objects[array_index] = val
|
209
263
|
end
|
210
264
|
|
211
|
-
#
|
265
|
+
# Ensures children's loaded_elments match the QuerySet's ones.
|
266
|
+
# @return [void]
|
212
267
|
def update_loaded_elements
|
213
268
|
|
214
269
|
return if currently_empty?
|
@@ -223,6 +278,7 @@ module Spider; module Model
|
|
223
278
|
@loaded_elements.merge!(f_loaded)
|
224
279
|
end
|
225
280
|
|
281
|
+
# @return [true] True if the QuerySet, or any of its children, has been modified since loading
|
226
282
|
def modified?
|
227
283
|
return true if @modified
|
228
284
|
@objects.each do |obj|
|
@@ -231,22 +287,29 @@ module Spider; module Model
|
|
231
287
|
return false
|
232
288
|
end
|
233
289
|
|
234
|
-
#
|
290
|
+
# @return [BaseModel] The last object in the QuerySet
|
235
291
|
def last
|
236
292
|
load unless (@loaded || !autoload?) && loaded?(total_rows-1)
|
237
293
|
@objects.last
|
238
294
|
end
|
239
295
|
|
240
|
-
#
|
296
|
+
# Removes the object at the given index from the QuerySet
|
297
|
+
# @param [Fixnum] index
|
298
|
+
# @return [BaseModel|nil] The removed object
|
241
299
|
def delete_at(index)
|
242
300
|
@objects.delete_at(index)
|
243
301
|
end
|
244
302
|
|
303
|
+
# Removes the given object from the QuerySet
|
304
|
+
# @param [BaseModel] obj
|
305
|
+
# @return [BaseModel|nil] The removed object
|
245
306
|
def delete(obj)
|
246
307
|
@objects.delete(obj)
|
247
308
|
end
|
248
309
|
|
249
310
|
# Returns a new QuerySet containing objects from both this and the other.
|
311
|
+
# @param [QuerySet] other
|
312
|
+
# @return [QuerySet]
|
250
313
|
def +(other)
|
251
314
|
qs = self.clone
|
252
315
|
other.each do |obj|
|
@@ -256,22 +319,27 @@ module Spider; module Model
|
|
256
319
|
end
|
257
320
|
|
258
321
|
# Number of objects fetched. Will call load if not loaded yet.
|
259
|
-
# Note: this is not the total number of objects
|
322
|
+
# Note: this is not the total number of objects responding to the Query;
|
260
323
|
# it may be equal to the fetch_window, or to the @query.limit.
|
324
|
+
# @return [Fixnum] length
|
261
325
|
def length
|
262
326
|
load unless @loaded || !autoload?
|
263
327
|
@objects.length
|
264
328
|
end
|
265
329
|
|
266
|
-
# Like #select, but returns an array
|
330
|
+
# Like {#select}, but returns an array
|
331
|
+
# @return [Array]
|
267
332
|
alias :select_array :select
|
268
333
|
|
269
334
|
# Returns a (static) QuerySet of the objects for which the block evaluates to true.
|
335
|
+
# @param [Proc] proc The block to evaluate
|
336
|
+
# @return [QuerySet]
|
270
337
|
def select(&proc)
|
271
338
|
return QuerySet.new(@model, select_array(&proc))
|
272
339
|
end
|
273
340
|
|
274
341
|
# True if the query had a limit, and more results can be fetched.
|
342
|
+
# @return [bool] True if there are more objects to fetch from the storage.
|
275
343
|
def has_more?
|
276
344
|
return true if autoload? && !@loaded
|
277
345
|
return false unless query.limit
|
@@ -280,26 +348,32 @@ module Spider; module Model
|
|
280
348
|
end
|
281
349
|
|
282
350
|
# Total number of objects that would be returned had the Query no limit.
|
351
|
+
# @return [Fixnum] The total number of rows corresponding to the Query (without limit).
|
283
352
|
def total_rows
|
284
353
|
return @total_rows ? @total_rows : (@total_rows = @model.mapper.count(@query.condition))
|
285
354
|
end
|
286
355
|
|
287
356
|
# Current number of objects fetched.
|
357
|
+
# @return [Fixnum]
|
288
358
|
def current_length
|
289
359
|
@objects.length
|
290
360
|
end
|
291
361
|
|
292
|
-
#
|
362
|
+
# Returns true if the QuerySet has no elements. Will load if the QuerySet is autoloading.
|
363
|
+
# @return [bool] True if QuerySet is empty
|
293
364
|
def empty?
|
294
365
|
load unless @loaded || !autoload?
|
295
366
|
@objects.empty?
|
296
367
|
end
|
297
368
|
|
369
|
+
# @return [bool] True if no object has been fetched yet.
|
298
370
|
def currently_empty?
|
299
371
|
@objects.empty?
|
300
372
|
end
|
301
373
|
|
302
374
|
# Index objects by some elements.
|
375
|
+
# @param [*Element] elements Elements to index on
|
376
|
+
# @return [self]
|
303
377
|
def index_by(*elements)
|
304
378
|
names = elements.map{ |el| (el.is_a?(Spider::Model::Element)) ? el.name.to_s : el.to_s }
|
305
379
|
index_name = names.sort.join(',')
|
@@ -308,8 +382,10 @@ module Spider; module Model
|
|
308
382
|
return self
|
309
383
|
end
|
310
384
|
|
385
|
+
|
311
386
|
# Rebuild object index.
|
312
|
-
|
387
|
+
# @return [self]
|
388
|
+
def reindex
|
313
389
|
@index_lookup.each_key do |index|
|
314
390
|
@index_lookup[index] = {}
|
315
391
|
end
|
@@ -320,6 +396,8 @@ module Spider; module Model
|
|
320
396
|
end
|
321
397
|
|
322
398
|
# Adds object to the index
|
399
|
+
# @param [BaseModel] obj
|
400
|
+
# @return [void]
|
323
401
|
def index_object(obj) # :nodoc:
|
324
402
|
@index_lookup.keys.each do |index_by|
|
325
403
|
names = index_by.split(',')
|
@@ -330,7 +408,9 @@ module Spider; module Model
|
|
330
408
|
end
|
331
409
|
end
|
332
410
|
|
333
|
-
#
|
411
|
+
# @param [BaseModel] obj
|
412
|
+
# @param [Symbol|String] name Element name
|
413
|
+
# @return [String] The index key for an object's element
|
334
414
|
def search_key(obj, name) # :nodoc:
|
335
415
|
sub = obj.is_a?(Hash) ? obj[name] : obj.get(name.to_sym)
|
336
416
|
if (sub.is_a?(Spider::Model::BaseModel))
|
@@ -346,17 +426,22 @@ module Spider; module Model
|
|
346
426
|
end
|
347
427
|
|
348
428
|
# Remove all elements from self
|
429
|
+
# @return [void]
|
349
430
|
def clear
|
350
431
|
@objects = []
|
351
432
|
@index_lookup.each_key{ |k| @index_lookup[k] = {} }
|
352
433
|
end
|
353
434
|
|
354
435
|
# Iterates on currently loaded objects
|
436
|
+
# @yield [BaseModel]
|
437
|
+
# @return [void]
|
355
438
|
def each_current
|
356
439
|
@objects.each { |obj| yield obj }
|
357
440
|
end
|
358
441
|
|
359
442
|
# Iterates on objects, loading when needed.
|
443
|
+
# @yield [BaseModel]
|
444
|
+
# @return [void]
|
360
445
|
def each
|
361
446
|
self.each_rolling_index do |i|
|
362
447
|
obj = @objects[i]
|
@@ -370,6 +455,8 @@ module Spider; module Model
|
|
370
455
|
|
371
456
|
# Iterates yielding the internal objects index. Will load when needed. If a window is
|
372
457
|
# used, the index will roll back to 0 on every window.
|
458
|
+
# @yield [BaseModel]
|
459
|
+
# @return [void]
|
373
460
|
def each_rolling_index
|
374
461
|
@window_current_start = nil if (@fetch_window)
|
375
462
|
while (!@fetch_window || has_more?)
|
@@ -382,6 +469,8 @@ module Spider; module Model
|
|
382
469
|
end
|
383
470
|
|
384
471
|
# Iterates yielding the queryset index. Will load when needed.
|
472
|
+
# @yield [Fixnum]
|
473
|
+
# @return [void]
|
385
474
|
def each_index
|
386
475
|
self.each_rolling_index do |i|
|
387
476
|
i += @window_current_start-1 if @window_current_start
|
@@ -390,6 +479,8 @@ module Spider; module Model
|
|
390
479
|
end
|
391
480
|
|
392
481
|
# Iterates on indexes without loading.
|
482
|
+
# @yield [Fixnum]
|
483
|
+
# @return [void]
|
393
484
|
def each_current_index
|
394
485
|
@objects.each_index do |i|
|
395
486
|
i += @window_current_start-1 if @window_current_start
|
@@ -398,11 +489,22 @@ module Spider; module Model
|
|
398
489
|
end
|
399
490
|
|
400
491
|
# Merges the content of another QuerySet.
|
492
|
+
# @param [QuerySet] query_set
|
493
|
+
# @return [void]
|
401
494
|
def merge(query_set)
|
402
495
|
@objects += query_set.instance_variable_get(:"@objects")
|
403
496
|
reindex
|
404
497
|
end
|
405
498
|
|
499
|
+
# Returns true if the QuerySet includes the given value.
|
500
|
+
#
|
501
|
+
# The value can be a BaseModel, which will be searched as it is;
|
502
|
+
#
|
503
|
+
# a Hash, in which case an Object with all the given values will be searched;
|
504
|
+
#
|
505
|
+
# or an Object, which will be searched as the (only) primary key of a contained model
|
506
|
+
# @param [BaseModel|Hash|Object] val The value to be checked
|
507
|
+
# @return [bool]
|
406
508
|
def include?(val)
|
407
509
|
self.each do |obj|
|
408
510
|
if val.is_a?(BaseModel)
|
@@ -424,6 +526,8 @@ module Spider; module Model
|
|
424
526
|
end
|
425
527
|
|
426
528
|
# Searchs the index for objects matching the given params.
|
529
|
+
# @param [Hash] params A set of conditions. Keys must match already created indexes.
|
530
|
+
# @return [QuerySet] A new QuerySet with objects matching params
|
427
531
|
def find(params)
|
428
532
|
sorted_keys = params.keys.map{|k| k.to_s}.sort.map{|k| k.to_sym}
|
429
533
|
index = sorted_keys.map{ |key| key.to_s }.join(',')
|
@@ -436,12 +540,16 @@ module Spider; module Model
|
|
436
540
|
return QuerySet.new(@model, result)
|
437
541
|
end
|
438
542
|
|
439
|
-
# Calls Query
|
543
|
+
# Calls {Query#order_by} on the QuerySet's query
|
544
|
+
# @param [*Element]
|
545
|
+
# @return [self]
|
440
546
|
def order_by(*elements)
|
441
|
-
@query.order_by
|
547
|
+
@query.order_by(*elements)
|
442
548
|
return self
|
443
549
|
end
|
444
550
|
|
551
|
+
# Calls {Query#with_polymorphs} on the QuerySet's query
|
552
|
+
# @return [self]
|
445
553
|
def with_polymorphs
|
446
554
|
@model.polymorphic_models.each do |model, attributes|
|
447
555
|
@query.with_polymorph(model)
|
@@ -450,6 +558,9 @@ module Spider; module Model
|
|
450
558
|
end
|
451
559
|
|
452
560
|
# Sets the value of an element on all currently loaded objects.
|
561
|
+
# @param [Element|Symbol] element
|
562
|
+
# @param [Object] value
|
563
|
+
# @return [void]
|
453
564
|
def set(element, value)
|
454
565
|
element_name = element.is_a?(Element) ? element.name : element
|
455
566
|
fixed(element_name, value)
|
@@ -462,6 +573,7 @@ module Spider; module Model
|
|
462
573
|
end
|
463
574
|
|
464
575
|
# Executes the query and fetches the objects; (the next batch if a fetch_window is set).
|
576
|
+
# @return [self]
|
465
577
|
def load
|
466
578
|
return self unless loadable?
|
467
579
|
clear
|
@@ -474,7 +586,8 @@ module Spider; module Model
|
|
474
586
|
return self
|
475
587
|
end
|
476
588
|
|
477
|
-
#
|
589
|
+
# @param [Fixnum] i
|
590
|
+
# @return [Fixnum] The index to start with to get the page containing the i-th element
|
478
591
|
def start_for_index(i) # :nodoc:
|
479
592
|
return 1 unless @fetch_window
|
480
593
|
page = i / @fetch_window + 1
|
@@ -482,6 +595,8 @@ module Spider; module Model
|
|
482
595
|
end
|
483
596
|
|
484
597
|
# Loads objects up to index i
|
598
|
+
# @param [Fixnum] i Index
|
599
|
+
# @return [void]
|
485
600
|
def load_to_index(i)
|
486
601
|
return load unless @fetch_window
|
487
602
|
page = i / @fetch_window + 1
|
@@ -489,6 +604,8 @@ module Spider; module Model
|
|
489
604
|
end
|
490
605
|
|
491
606
|
# Loads the next batch of objects.
|
607
|
+
# @param [Fixnum] Page to load (defaults to next page)
|
608
|
+
# @return [self]
|
492
609
|
def load_next(page=nil)
|
493
610
|
if (@fetch_window)
|
494
611
|
@query.limit = @fetch_window
|
@@ -507,7 +624,9 @@ module Spider; module Model
|
|
507
624
|
end
|
508
625
|
|
509
626
|
# If a Fixnum is passed, will tell if the given index is loaded.
|
510
|
-
# With no argument, will tell if the QuerySet is loaded
|
627
|
+
# With no argument, will tell if the QuerySet is fully loaded
|
628
|
+
# @param [Fixnum] index
|
629
|
+
# @return [bool]
|
511
630
|
def loaded?(index=nil)
|
512
631
|
return @loaded if !@loaded || !index || !@fetch_window
|
513
632
|
return false unless @window_current_start
|
@@ -515,35 +634,45 @@ module Spider; module Model
|
|
515
634
|
return false
|
516
635
|
end
|
517
636
|
|
637
|
+
# Sets that the QuerySet is or is not loaded
|
638
|
+
# @param [bool] val
|
639
|
+
# @return [void]
|
518
640
|
def loaded=(val)
|
519
641
|
@loaded = val
|
520
642
|
@modified = false if @loaded
|
521
643
|
end
|
522
644
|
|
645
|
+
# @return [bool] True if the QuerySet can be loaded
|
523
646
|
def loadable?
|
524
647
|
@loadable
|
525
648
|
end
|
526
649
|
|
527
650
|
# Saves each object in the QuerySet.
|
651
|
+
# @return [void]
|
528
652
|
def save
|
529
653
|
no_autoload(false){ each{ |obj| obj.save } }
|
530
654
|
end
|
531
655
|
|
656
|
+
# Calls {BaseModel.save!} on each object in the QuerySet.
|
657
|
+
# @return [void]
|
532
658
|
def save!
|
533
659
|
no_autoload(false){ each{ |obj| obj.save! } }
|
534
660
|
end
|
535
661
|
|
536
|
-
# Calls
|
662
|
+
# Calls {BaseModel.insert} on each object in the QuerySet.
|
663
|
+
# @return [void]
|
537
664
|
def insert
|
538
665
|
no_autoload(false){ each{ |obj| obj.insert } }
|
539
666
|
end
|
540
667
|
|
541
|
-
# Calls
|
668
|
+
# Calls {BaseModel.update} on each object in the QuerySet.
|
669
|
+
# @return [void]
|
542
670
|
def update
|
543
671
|
no_autoload(false){ each{ |obj| obj.update } }
|
544
672
|
end
|
545
673
|
|
546
|
-
# Calls
|
674
|
+
# Calls {BaseModel.save_all} on each object in the QuerySet.
|
675
|
+
# @return [void]
|
547
676
|
def save_all(params={})
|
548
677
|
@objects.each do |obj|
|
549
678
|
# next if (unit_of_work && !unit_of_work.save?(obj))
|
@@ -552,6 +681,8 @@ module Spider; module Model
|
|
552
681
|
end
|
553
682
|
|
554
683
|
# Returns a new instance of @model from val.
|
684
|
+
# @param [Object] val
|
685
|
+
# @return [BaseModel] The created object
|
555
686
|
def instantiate_object(val=nil)
|
556
687
|
if (@append_element && !val.is_a?(@model) && !(val.is_a?(Hash) && val[@append_element]))
|
557
688
|
val = @model.elements[@append_element].type.new(val) unless (val.is_a?(BaseModel))
|
@@ -567,10 +698,12 @@ module Spider; module Model
|
|
567
698
|
return obj
|
568
699
|
end
|
569
700
|
|
701
|
+
# @return [String] A textual description of the QuerySet
|
570
702
|
def inspect
|
571
703
|
return "#{self.class.name}:\n@model=#{@model}, @query=#{query.inspect}, @objects=#{@objects.inspect}"
|
572
704
|
end
|
573
705
|
|
706
|
+
# @return [String] The JSON representation of the QuerySet
|
574
707
|
def to_json(state=nil, &proc)
|
575
708
|
load unless loaded? || !autoload?
|
576
709
|
res = "[" +
|
@@ -580,17 +713,20 @@ module Spider; module Model
|
|
580
713
|
end
|
581
714
|
|
582
715
|
|
583
|
-
#
|
716
|
+
# @param [*Object] (see {BaseModel.cut})
|
717
|
+
# @return [Array] An array with the results of calling {BaseModel.cut} on each object.
|
584
718
|
def cut(*params)
|
585
719
|
load unless loaded? || !autoload?
|
586
720
|
return self.map{ |obj| obj.cut(*params) }
|
587
721
|
end
|
588
722
|
|
589
|
-
#
|
723
|
+
# @return [Array] An array with the results of calling #BaseModel.to_hash_array on each object.
|
590
724
|
def to_hash_array
|
591
725
|
return self.map{ |obj| obj.to_hash }
|
592
726
|
end
|
593
727
|
|
728
|
+
# @param [String|Symbol] Element name (or dotted element path) to index by
|
729
|
+
# @return [Hash] A Hash, indexed by the value of element on the object
|
594
730
|
def to_indexed_hash(element)
|
595
731
|
hash = {}
|
596
732
|
self.each do |row|
|
@@ -599,7 +735,8 @@ module Spider; module Model
|
|
599
735
|
hash
|
600
736
|
end
|
601
737
|
|
602
|
-
# Prints an ASCII table
|
738
|
+
# Prints an ASCII table of the QuerySet
|
739
|
+
# @return [void]
|
603
740
|
def table
|
604
741
|
|
605
742
|
# Functions for determining terminal size:
|
@@ -674,14 +811,17 @@ module Spider; module Model
|
|
674
811
|
|
675
812
|
end
|
676
813
|
|
814
|
+
# @return [Array] The Array corresponding to the QuerySet
|
677
815
|
def to_a
|
678
816
|
self.map{ |row| row }
|
679
817
|
end
|
680
818
|
|
819
|
+
# @return [Array] A reversed Array
|
681
820
|
def reverse
|
682
821
|
self.to_a.reverse
|
683
822
|
end
|
684
823
|
|
824
|
+
# @return [Array] Calls map on currently loaded objects
|
685
825
|
def map_current
|
686
826
|
a = []
|
687
827
|
each_current{ |row| a << yield(row) }
|
@@ -689,6 +829,7 @@ module Spider; module Model
|
|
689
829
|
end
|
690
830
|
|
691
831
|
# Returns an array of Hashes, with each value of the object is converted to string.
|
832
|
+
# @return [Array]
|
692
833
|
def to_flat_array
|
693
834
|
map do |obj|
|
694
835
|
h = {}
|
@@ -699,18 +840,25 @@ module Spider; module Model
|
|
699
840
|
end
|
700
841
|
end
|
701
842
|
|
843
|
+
# Removes the objects for which the block returns true from the QuerySet
|
844
|
+
# @yield [BaseModel]
|
845
|
+
# @return [void]
|
702
846
|
def reject!(&proc)
|
703
847
|
@objects.reject!(&proc)
|
704
848
|
end
|
705
849
|
|
850
|
+
# Removes all objects from the QuerySet
|
851
|
+
# @return [void]
|
706
852
|
def empty!
|
707
853
|
@objects = []
|
708
854
|
end
|
709
855
|
|
856
|
+
# @return [String] All the objects, to_s, joined by ', '
|
710
857
|
def to_s
|
711
858
|
self.map{ |o| o.to_s }.join(', ')
|
712
859
|
end
|
713
860
|
|
861
|
+
# Missing methods will be sent to the query
|
714
862
|
def method_missing(method, *args, &proc)
|
715
863
|
el = @model.elements[method]
|
716
864
|
if (el && el.model? && el.reverse)
|
@@ -720,6 +868,8 @@ module Spider; module Model
|
|
720
868
|
return super
|
721
869
|
end
|
722
870
|
|
871
|
+
# @param [Element|Symbol] element
|
872
|
+
# @return [QuerySet] The QuerySet corresponding to an element in the current QuerySet
|
723
873
|
def element_queryset(el)
|
724
874
|
el = @model.elements[el] if el.is_a?(Symbol)
|
725
875
|
condition = el.condition
|
@@ -735,6 +885,8 @@ module Spider; module Model
|
|
735
885
|
# Given a dotted path, will return an array of all objects reachable by that path
|
736
886
|
# Example
|
737
887
|
# objectset.all_children('friends.collegues.addresses.street_name')
|
888
|
+
# @param [String] path
|
889
|
+
# @return [Array] An array of all found objects
|
738
890
|
def all_children(path)
|
739
891
|
if (path.length > 0)
|
740
892
|
children = @objects.map{ |obj| obj.all_children(path.clone) }.flatten
|
@@ -744,28 +896,36 @@ module Spider; module Model
|
|
744
896
|
end
|
745
897
|
|
746
898
|
# Registers that the element has been loaded.
|
899
|
+
# @param [Element|Symbol]
|
900
|
+
# @return [void]
|
747
901
|
def element_loaded(element)
|
748
902
|
element = element.name if element.is_a?(Element)
|
749
903
|
@loaded_elements[element] = true
|
750
904
|
end
|
751
905
|
|
752
|
-
#
|
906
|
+
# @param [Element|Symbol]
|
907
|
+
# @return [bool] True if the element has been loaded from the Storage.
|
753
908
|
def element_loaded?(element)
|
754
909
|
element = element.name if element.is_a?(Element)
|
755
910
|
@loaded_elements[element]
|
756
911
|
end
|
757
912
|
|
758
|
-
# Returns the QuerySet IdentityMapper instance
|
913
|
+
# Returns the current QuerySet IdentityMapper instance, or instantiates a new one
|
914
|
+
# @return [IdentityMapper] The IdentityMapper
|
759
915
|
def identity_mapper
|
760
916
|
return Spider::Model.identity_mapper if Spider::Model.identity_mapper
|
761
917
|
@identity_mapper ||= IdentityMapper.new
|
762
918
|
end
|
763
919
|
|
764
|
-
# Assigns an IdentityMapper
|
920
|
+
# Assigns an IdentityMapper to the QuerySet
|
921
|
+
# @param [IdentityMapper] im
|
922
|
+
# @return [void]
|
765
923
|
def identity_mapper=(im)
|
766
924
|
@identity_mapper = im
|
767
925
|
end
|
768
926
|
|
927
|
+
# Calls {Query#with_superclass} on the query.
|
928
|
+
# @return [self]
|
769
929
|
def with_superclass
|
770
930
|
@query.with_superclass
|
771
931
|
return self
|
@@ -775,29 +935,35 @@ module Spider; module Model
|
|
775
935
|
# Condition, request and query methods #
|
776
936
|
########################################
|
777
937
|
|
778
|
-
# Calls #
|
938
|
+
# Calls {Query#where} on the query.
|
939
|
+
# @return {self}
|
779
940
|
def where(*params, &proc)
|
780
941
|
@query.where(*params, &proc)
|
781
942
|
return self
|
782
943
|
end
|
783
944
|
|
784
|
-
# Calls
|
945
|
+
# Calls {Query.limit} on the query
|
946
|
+
# @return {self}
|
785
947
|
def limit(n)
|
786
948
|
@query.limit = n
|
787
949
|
return self
|
788
950
|
end
|
789
951
|
|
790
|
-
# Calls
|
952
|
+
# Calls {Query.offset}
|
953
|
+
# @return {self}
|
791
954
|
def offset(n)
|
792
955
|
@query.offset = n
|
793
956
|
return self
|
794
957
|
end
|
795
958
|
|
959
|
+
# Calls {Query.page} on the Query
|
960
|
+
# @return {self}
|
796
961
|
def page(page, rows)
|
797
962
|
@query.page(page, rows)
|
798
963
|
self
|
799
964
|
end
|
800
965
|
|
966
|
+
# @return [Fixnum|nil] Total number of available pages for current query (or nil if no limit is set)
|
801
967
|
def pages
|
802
968
|
return nil unless @query.limit
|
803
969
|
(self.total_rows.to_f / @query.limit).ceil
|
@@ -808,6 +974,7 @@ module Spider; module Model
|
|
808
974
|
# end
|
809
975
|
|
810
976
|
# Performs a deep copy
|
977
|
+
# @return [QuerySet]
|
811
978
|
def clone
|
812
979
|
c = self.class.new(self.model, self.query.clone)
|
813
980
|
c.autoload = self.autoload?
|