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
data/lib/spiderfw/model/model.rb
CHANGED
@@ -4,6 +4,11 @@ require 'spiderfw/model/identity_mapper'
|
|
4
4
|
|
5
5
|
module Spider
|
6
6
|
|
7
|
+
# Spider::Model is the namespace containing all data-related classes and modules.
|
8
|
+
#
|
9
|
+
# In addition, it implements some helper methods.
|
10
|
+
#
|
11
|
+
# See {BaseModel} for the base class that must be subclassed by app's models.
|
7
12
|
module Model
|
8
13
|
|
9
14
|
@base_types = [
|
@@ -11,17 +16,23 @@ module Spider
|
|
11
16
|
Spider::DataTypes::Bool, Spider::DataTypes::PK
|
12
17
|
]
|
13
18
|
|
14
|
-
#
|
15
|
-
#
|
19
|
+
# Returns a list of the base types, which must be handled by all mappers.
|
20
|
+
#
|
16
21
|
# String, Spider::DataTypes::Text, Fixnum, Float, BigDecimal, Date, DateTime, Spider::DataTypes::Bool.
|
17
22
|
#
|
18
23
|
# These types must be handled by all mappers.
|
24
|
+
# @return [Array] An array of base types
|
19
25
|
def self.base_types
|
20
26
|
@base_types
|
21
27
|
end
|
22
28
|
|
23
|
-
# Returns the base type corresponding to class.
|
24
|
-
#
|
29
|
+
# Returns the base type corresponding to a class.
|
30
|
+
#
|
31
|
+
# For BaseModels, the class itself will be returned; otherwise, will walk superclasses and DataType info
|
32
|
+
# until one of the {Model.base_types} is found.
|
33
|
+
#
|
34
|
+
# @param [Class] class
|
35
|
+
# @return [Class] The Base Type
|
25
36
|
def self.base_type(klass)
|
26
37
|
k = klass
|
27
38
|
while (k && !base_types.include?(k))
|
@@ -30,8 +41,9 @@ module Spider
|
|
30
41
|
return k
|
31
42
|
end
|
32
43
|
|
33
|
-
#
|
34
|
-
|
44
|
+
# @param [Class] A DataType subclass
|
45
|
+
# @return [Class] The Ruby class corresponding to a Spider DataType
|
46
|
+
def self.ruby_type(klass)
|
35
47
|
map_types = {
|
36
48
|
Spider::DataTypes::Text => String,
|
37
49
|
Spider::DataTypes::Bool => FalseClass,
|
@@ -42,8 +54,11 @@ module Spider
|
|
42
54
|
return klass
|
43
55
|
end
|
44
56
|
|
57
|
+
# @private
|
45
58
|
# An iteration in the search for base type.
|
46
|
-
|
59
|
+
# @param [Class] class
|
60
|
+
# @return [Class] simplified type
|
61
|
+
def self.simplify_type(klass)
|
47
62
|
map_types = {
|
48
63
|
|
49
64
|
}
|
@@ -56,7 +71,12 @@ module Spider
|
|
56
71
|
end
|
57
72
|
|
58
73
|
|
59
|
-
#
|
74
|
+
# Retrieves an object corresponding to gived values from the IdentityMapper, or puts it there if not found.
|
75
|
+
# @param [Class>BaseModel] The model
|
76
|
+
# @parm [Object] val A BaseModel instance, or a Hash of values, or a primary key for the model
|
77
|
+
# @param [bool] set_loaded If true, when instantiating an object from hash values, set the values as
|
78
|
+
# if they were loaded from the storage
|
79
|
+
# @return [BaseModel] The object retrieved from the IdentityMapper
|
60
80
|
def self.get(model, val=nil, set_loaded=false)
|
61
81
|
if (val && !val.is_a?(Hash))
|
62
82
|
if (model.primary_keys.length == 1)
|
@@ -73,6 +93,10 @@ module Spider
|
|
73
93
|
end
|
74
94
|
|
75
95
|
# Puts an object into the IdentityMapper
|
96
|
+
# @param [BaseMode] object to place into the IdentityMapper
|
97
|
+
# @param [bool] check If true, if the object already exists in the IdentityMapper it will be merged.
|
98
|
+
# If false, if the object already exists it will be overwritten.
|
99
|
+
# @return [BaseModel] The object, as present in the IdentityMapper after the put
|
76
100
|
def self.put(obj, check=false)
|
77
101
|
if (identity_mapper)
|
78
102
|
return identity_mapper.put(obj, check)
|
@@ -81,24 +105,35 @@ module Spider
|
|
81
105
|
end
|
82
106
|
end
|
83
107
|
|
84
|
-
|
108
|
+
# @return [IdentityMapper] The current IdentityMapper, if active
|
109
|
+
def self.identity_mapper
|
85
110
|
Spider.current[:identity_mapper]
|
86
111
|
end
|
87
112
|
|
88
|
-
|
113
|
+
# @param [IdentityMapper] im The IdentityMapper to activate for the current request
|
114
|
+
# @return [IdentityMapper]
|
115
|
+
def self.identity_mapper=(im)
|
89
116
|
Spider.current[:identity_mapper] = im
|
90
117
|
end
|
91
118
|
|
119
|
+
# Starts a new Unit Of Work
|
120
|
+
# @return [UnitOfWork]
|
92
121
|
def self.start_unit_of_work
|
93
122
|
uow = UnitOfWork.new
|
94
123
|
uow.start
|
95
124
|
end
|
96
125
|
|
126
|
+
# Stops the current Unit Of Work
|
127
|
+
# @return [void]
|
97
128
|
def self.stop_unit_of_work
|
98
129
|
Spider.current[:unit_of_work].stop
|
99
130
|
end
|
100
131
|
|
101
|
-
|
132
|
+
# @param [Proc] proc If supplied and no Unit Of Work is running, executes the block inside
|
133
|
+
# a new Unit Of Work
|
134
|
+
# @return [UnitOfWork] the current Unit Of Work, if no block was passed; otherwise, the Unit Of Work that
|
135
|
+
# was used to run the block
|
136
|
+
def self.unit_of_work(&proc)
|
102
137
|
uow = Spider.current[:unit_of_work]
|
103
138
|
if !uow
|
104
139
|
if proc
|
@@ -108,17 +143,28 @@ module Spider
|
|
108
143
|
return uow
|
109
144
|
end
|
110
145
|
|
111
|
-
|
146
|
+
# Sets the UnitOfWork to use for the current request
|
147
|
+
# @param [UnitOfWork] uow
|
148
|
+
# @return [UnitOfWork]
|
112
149
|
def self.unit_of_work=(uow)
|
113
150
|
Spider.current[:unit_of_work] = uow
|
114
151
|
end
|
115
152
|
|
153
|
+
# Executes a block inside a new Unit Of Work
|
154
|
+
#
|
155
|
+
# **Note**: you should almost always use {Model.in_unit} instead, since
|
156
|
+
# a Unit Of Work without an Identity Mapper can be problematic.
|
157
|
+
# @param [Proc] proc The block to execute
|
158
|
+
# @return [UnitOfWork] The Unit Of Work that was used to run the block
|
116
159
|
def self.with_unit_of_work(&proc)
|
117
160
|
with_identity_mapper do
|
118
161
|
return unit_of_work(&proc)
|
119
162
|
end
|
120
163
|
end
|
121
164
|
|
165
|
+
# Executes a block without running in Unit Of Work
|
166
|
+
# @param [Proc] proc The block to run without a unit of work
|
167
|
+
# @return [UnitOfWork] The previously active Unit Of Work (if any)
|
122
168
|
def self.no_unit_of_work(&proc)
|
123
169
|
uow = self.unit_of_work
|
124
170
|
self.unit_of_work = nil
|
@@ -126,10 +172,14 @@ module Spider
|
|
126
172
|
self.unit_of_work = uow
|
127
173
|
end
|
128
174
|
|
175
|
+
# @return [bool] True if there is an active Unit Of Work, false otherwise
|
129
176
|
def self.unit_of_work_running?
|
130
177
|
self.unit_of_work && self.unit_of_work.running?
|
131
178
|
end
|
132
179
|
|
180
|
+
# Executes a block without Identity Mapper
|
181
|
+
# @param [Proc] proc The block to run without the Identity Mapper
|
182
|
+
# @return [IdentityMapper] The previously active Identity Mapper (if any)
|
133
183
|
def self.no_identity_mapper(&proc)
|
134
184
|
im = self.identity_mapper
|
135
185
|
self.identity_mapper = nil
|
@@ -137,6 +187,9 @@ module Spider
|
|
137
187
|
self.identity_mapper = im
|
138
188
|
end
|
139
189
|
|
190
|
+
# Executes a block without Identity Mapper and Unit Of Work
|
191
|
+
# @param [Proc] proc The block to run
|
192
|
+
# @return [UnitOfWork] The previously active Unit Of Work (if any)
|
140
193
|
def self.no_context(&proc)
|
141
194
|
uow = self.unit_of_work
|
142
195
|
self.unit_of_work = nil
|
@@ -148,7 +201,10 @@ module Spider
|
|
148
201
|
|
149
202
|
end
|
150
203
|
|
151
|
-
# Executes
|
204
|
+
# Executes a block in the context of the current IdentityMapper, if one is active.
|
205
|
+
# If no IdentityMapper is running, the code is executed inside a new Identity Mapper
|
206
|
+
# @param [Proc] proc The block to run
|
207
|
+
# @return [IdentityMapper] The used Identity Mapper
|
152
208
|
def self.with_identity_mapper(&proc)
|
153
209
|
if identity_mapper
|
154
210
|
yield identity_mapper
|
@@ -159,6 +215,9 @@ module Spider
|
|
159
215
|
end
|
160
216
|
end
|
161
217
|
|
218
|
+
# Executes a block inside a Unit Of Work and Identity Mapper
|
219
|
+
# @param [Proc] proc The block to run
|
220
|
+
# @return [void]
|
162
221
|
def self.in_unit(&proc)
|
163
222
|
uow = self.unit_of_work
|
164
223
|
self.start_unit_of_work unless uow
|
@@ -172,10 +231,16 @@ module Spider
|
|
172
231
|
|
173
232
|
end
|
174
233
|
|
175
|
-
# Syncs the schema with the storage.
|
176
|
-
|
177
|
-
#
|
178
|
-
|
234
|
+
# Syncs the schema for a model, or for all models within an app, with the storage.
|
235
|
+
# @param [Class>BaseModel|Module>Spider::App] model_or_app
|
236
|
+
# @param [bool] force If true, allow operations that could cause data loss
|
237
|
+
# @param [Hash] options Options can be:
|
238
|
+
# * :no_sync Don't actually run the sync, only check the operations to run
|
239
|
+
# * :drop_tables Drop unneeded tables
|
240
|
+
# @return [void]
|
241
|
+
def self.sync_schema(model_or_app, force=false, options={})
|
242
|
+
|
243
|
+
# FIXME: this is clearly db specific. Move somewhere else.
|
179
244
|
models = []
|
180
245
|
mod = const_get_full(model_or_app)
|
181
246
|
if (mod.is_a?(Module) && mod.include?(Spider::App))
|
@@ -215,7 +280,9 @@ module Spider
|
|
215
280
|
end
|
216
281
|
end
|
217
282
|
|
218
|
-
# Load YAML data
|
283
|
+
# Load YAML data to the storage
|
284
|
+
# @param [String] file File to load data from
|
285
|
+
# @param [bool] truncate If true, delete all data from the models in the file before inserting new data
|
219
286
|
def self.load_fixtures(file, truncate=false)
|
220
287
|
if (file =~ /\.([^\.]+)$/)
|
221
288
|
extension = $1
|
@@ -257,19 +324,23 @@ module Spider
|
|
257
324
|
end
|
258
325
|
|
259
326
|
# Generic Model error.
|
260
|
-
|
261
327
|
class ModelException < RuntimeError
|
262
328
|
end
|
263
329
|
|
264
330
|
# Error raised when data can't be accepted.
|
265
|
-
|
266
331
|
class FormatError < ::FormatError
|
267
|
-
|
332
|
+
# @return [Element]
|
333
|
+
attr_reader :element
|
334
|
+
# @return [Object]
|
335
|
+
attr_reader :value
|
268
336
|
|
269
337
|
# Takes an Element, the value, and a message.
|
270
338
|
# The message should be a format specification; it will be %'d with the value.
|
271
339
|
# error = FormatError.new(my_element, 3, "Element value %s is wrong.")
|
272
340
|
# error.to_s => "Element value 3 is wrong."
|
341
|
+
# @param [Element] value
|
342
|
+
# @param [Object] value
|
343
|
+
# @param [String] message The error message
|
273
344
|
def initialize(element, value, message)
|
274
345
|
@element = element
|
275
346
|
@message = message
|
@@ -287,9 +358,20 @@ module Spider
|
|
287
358
|
|
288
359
|
end
|
289
360
|
|
361
|
+
# Error raised when data is of the wrong type
|
290
362
|
class TypeError < ArgumentError
|
291
363
|
end
|
292
364
|
|
365
|
+
# Sorts an Array of models, placing subclasses before superclasses.
|
366
|
+
#
|
367
|
+
# If :association_dependencies is true, models having an association to another model will be placed after the associated
|
368
|
+
# model.
|
369
|
+
#
|
370
|
+
# This can be used to insert a dump of data, ensuring later models only depend on already inserted objects.
|
371
|
+
# @param [Array] models An array of BaseModel subclasses
|
372
|
+
# @param [Hash] options Options can be:
|
373
|
+
# * :association_dependencies If true, sort associated models before the model associating them
|
374
|
+
# @return [Array] The sorted array
|
293
375
|
def self.sort(models, options={})
|
294
376
|
options = {
|
295
377
|
:association_dependencies => true
|
@@ -300,6 +382,7 @@ module Spider
|
|
300
382
|
|
301
383
|
require 'tsort'
|
302
384
|
|
385
|
+
# Helper class from sorting models using TSort
|
303
386
|
class Sorter
|
304
387
|
include TSort
|
305
388
|
|
@@ -351,6 +434,7 @@ module Spider
|
|
351
434
|
|
352
435
|
end
|
353
436
|
|
437
|
+
# Helper class for sorting models
|
354
438
|
class SortTask
|
355
439
|
attr_reader :model, :dependencies
|
356
440
|
|
@@ -11,18 +11,24 @@ module Spider; module Model
|
|
11
11
|
# mh['test.name'] = 'Devilish Kitty'
|
12
12
|
# => {:test => {:name => 'Devilish Kitty', :color => 'black'}}
|
13
13
|
class ModelHash < Hash
|
14
|
-
|
14
|
+
# Original hash value assignment
|
15
|
+
alias :modelhash_orig_set :[]=
|
15
16
|
|
17
|
+
# @param [Hash] hash A Hash to get data from
|
16
18
|
def initialize(hash=nil)
|
17
19
|
super()
|
18
20
|
merge!(hash) if (hash && hash.is_a?(Hash))
|
19
21
|
end
|
20
22
|
|
21
23
|
# Returns a new instance when needed by an assignement. May be overridden by subclasses.
|
24
|
+
# @return [ModelHash]
|
22
25
|
def get_deep_obj
|
23
26
|
return self.class.new
|
24
27
|
end
|
25
28
|
|
29
|
+
# Value assignment
|
30
|
+
# @param [String|Symbol|Element] key
|
31
|
+
# @param [Object] value
|
26
32
|
def []=(key, val)
|
27
33
|
if (val.is_a?(BaseModel))
|
28
34
|
n = self.class.new
|
@@ -43,6 +49,8 @@ module Spider; module Model
|
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
52
|
+
# Value retrieval
|
53
|
+
# @param [String|Symbol|Element] key
|
46
54
|
def [](key)
|
47
55
|
# TODO: deep
|
48
56
|
key = key.name if key.is_a?(Element)
|
data/lib/spiderfw/model/query.rb
CHANGED
@@ -8,27 +8,41 @@ module Spider; module Model
|
|
8
8
|
|
9
9
|
class Query
|
10
10
|
# An array of element-direction (:asc or :desc) pairs
|
11
|
+
# @return [Array]
|
11
12
|
attr_accessor :order
|
12
13
|
# Skip the first :offset objects
|
14
|
+
# @return [Fixnum]
|
13
15
|
attr_accessor :offset
|
14
16
|
# Limit the returned results to :limit objects
|
17
|
+
# @return [Fixnum]
|
15
18
|
attr_accessor :limit
|
16
19
|
# Requests subclasses of the queried model
|
20
|
+
# @return [Array]
|
17
21
|
attr_accessor :polymorphs
|
18
22
|
# The Condition instance
|
23
|
+
# @return [Condition]
|
19
24
|
attr_reader :condition
|
20
25
|
# The Request instance
|
26
|
+
# @return [Request]
|
21
27
|
attr_reader :request
|
28
|
+
# @return [Fixnum] number of rows per page, when using pagination
|
22
29
|
attr_reader :page_rows
|
30
|
+
# @return [Fixnum] current page, when using pagination
|
23
31
|
attr_reader :page
|
32
|
+
# @return [Array] Elements the mapper has to group_by
|
24
33
|
attr_accessor :group_by_elements
|
25
34
|
|
26
35
|
# Instantiates a new query, calling Condition#where on the condition.
|
36
|
+
# See {Query#new} for arguments
|
37
|
+
# Return #{Condition}
|
27
38
|
def self.where(*params)
|
28
39
|
return self.class.new.condition.where(*params)
|
29
40
|
end
|
30
41
|
|
31
42
|
# Parameters are a Condition and a Request. If a block is given, it will be parsed by the Condition.
|
43
|
+
# @param [Condition] condition
|
44
|
+
# @param [Request] request
|
45
|
+
# @param [Proc] proc Optional block used to construct the Condition
|
32
46
|
def initialize(condition = nil, request=nil, &proc)
|
33
47
|
@condition = condition.is_a?(Condition) ? condition : Condition.new(condition)
|
34
48
|
@request = request.is_a?(Request) ? request : Request.new(request)
|
@@ -39,7 +53,10 @@ module Spider; module Model
|
|
39
53
|
end
|
40
54
|
end
|
41
55
|
|
42
|
-
# Sets the condition. If val is not a Condition, will attempt to convert it to one
|
56
|
+
# Sets the condition. If val is not a Condition, will attempt to convert it to one
|
57
|
+
# (val will be passed to {Condition.new}).
|
58
|
+
# @param [Condition|Object]
|
59
|
+
# @return [void]
|
43
60
|
def condition=(val)
|
44
61
|
if (!val.is_a?(Condition))
|
45
62
|
@condition = Condition.new(val)
|
@@ -48,7 +65,10 @@ module Spider; module Model
|
|
48
65
|
end
|
49
66
|
end
|
50
67
|
|
51
|
-
# Sets the request. If val is not a Request, will attempt to convert it to one
|
68
|
+
# Sets the request. If val is not a Request, will attempt to convert it to one
|
69
|
+
# (val will be passed to {Request.new}).
|
70
|
+
# @param [Request|Object]
|
71
|
+
# @return [void]
|
52
72
|
def request=(val)
|
53
73
|
if (!val.is_a?(Request))
|
54
74
|
@request = Request.new(val)
|
@@ -65,6 +85,8 @@ module Spider; module Model
|
|
65
85
|
# Example:
|
66
86
|
# query.order_by(:element, :desc)
|
67
87
|
# query.order_by('name desc', :rating)
|
88
|
+
# @param [*Symbol|String] elements A list of elements
|
89
|
+
# @return [self]
|
68
90
|
def order_by(*elements)
|
69
91
|
if (elements.length == 2 && [:asc, :desc].include?(elements[1]))
|
70
92
|
@order << elements
|
@@ -84,6 +106,9 @@ module Spider; module Model
|
|
84
106
|
return self
|
85
107
|
end
|
86
108
|
|
109
|
+
# Elements to group_by (used by some mappers for aggregate queries)
|
110
|
+
# @param [*Symbol|String] elements A list of elements
|
111
|
+
# @return [self]
|
87
112
|
def group_by(*elements)
|
88
113
|
@group_by_elements ||= []
|
89
114
|
@group_by_elements += elements
|
@@ -91,6 +116,8 @@ module Spider; module Model
|
|
91
116
|
end
|
92
117
|
|
93
118
|
# Adds each element in the given list to the request.
|
119
|
+
# @param [*Symbol|String] elements A list of elements
|
120
|
+
# @return [self]
|
94
121
|
def select(*elements)
|
95
122
|
elements.each do |element|
|
96
123
|
@request.request(element.to_s)
|
@@ -100,13 +127,19 @@ module Spider; module Model
|
|
100
127
|
|
101
128
|
# Takes an argument or a block.
|
102
129
|
# If given an argument, will use it as a Condition. If given a block, will use it on the Condition.
|
130
|
+
# @param [Condition] condition
|
131
|
+
# @param [Proc] proc Block used to construct the Condition
|
103
132
|
def where(condition=nil, &proc)
|
104
133
|
condition = Condition.new(&proc) unless (condition)
|
105
134
|
@condition << condition
|
106
135
|
return self
|
107
136
|
end
|
108
137
|
|
109
|
-
# Requests a polymorph.
|
138
|
+
# Requests a polymorph. This means that the mapper will try to differentiate the result into
|
139
|
+
# the subclasses given here.
|
140
|
+
# @param [Class<BaseModel] type The polymorph class to look for
|
141
|
+
# @param [Request] request Additional elements of the subclass to request
|
142
|
+
# @return [self]
|
110
143
|
def with_polymorph(type, request=nil)
|
111
144
|
query = self.class.new(query) unless query.is_a?(self.class)
|
112
145
|
@polymorphs << type
|
@@ -119,28 +152,34 @@ module Spider; module Model
|
|
119
152
|
end
|
120
153
|
|
121
154
|
# Requests only polymorphs. (see Request#only_polymorphs).
|
155
|
+
# @return [Request]
|
122
156
|
def only_polymorphs
|
123
157
|
@request.only_polymorphs
|
124
158
|
end
|
125
159
|
|
160
|
+
# Load also objects that belong to the superclass, and don't have this subclass.
|
161
|
+
# See #Request#with_superclass.
|
162
|
+
# @return [Request]
|
126
163
|
def with_superclass
|
127
164
|
@request.with_superclass
|
128
165
|
end
|
129
166
|
|
130
|
-
|
131
|
-
|
132
|
-
end
|
133
|
-
|
167
|
+
# Request only the first result.
|
168
|
+
# @return [void]
|
134
169
|
def only_one
|
135
170
|
self.limit = 1
|
136
171
|
@only_one = true
|
137
172
|
end
|
138
173
|
|
139
|
-
|
174
|
+
# @return [bool] Was only the first record requested?
|
140
175
|
def only_one?
|
141
176
|
@only_one
|
142
177
|
end
|
143
178
|
|
179
|
+
# Pagination: request the given page, for given rows per page
|
180
|
+
# @param [Fixnum] page
|
181
|
+
# @param [Fixnum] rows
|
182
|
+
# @return [self]
|
144
183
|
def page(page, rows)
|
145
184
|
page = page.to_i
|
146
185
|
page = 1 if page == 0
|
@@ -156,11 +195,13 @@ module Spider; module Model
|
|
156
195
|
# information methods #
|
157
196
|
##############################
|
158
197
|
|
159
|
-
|
198
|
+
# @return [bool] Are there requested polymorphs?
|
199
|
+
def polymorphs?
|
160
200
|
@polymorphs.length > 0
|
161
201
|
end
|
162
202
|
|
163
203
|
# Returns a deep copy.
|
204
|
+
# @return [Query]
|
164
205
|
def clone
|
165
206
|
cl = self.class.new(@condition.clone, @request.clone)
|
166
207
|
cl.order = @order.clone
|