spiderfw 0.6.23 → 0.6.24
Sign up to get free protection for your applications and to get access to all the features.
- 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?
|