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
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
|