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.
Files changed (74) hide show
  1. data/CHANGELOG +10 -1
  2. data/README.rdoc +1 -1
  3. data/VERSION +1 -1
  4. data/apps/config_editor/_init.rb +1 -2
  5. data/apps/config_editor/controllers/config_editor_controller.rb +1 -7
  6. data/apps/core/admin/controllers/admin_controller.rb +1 -1
  7. data/apps/core/admin/public/css/sass/admin.css +35 -31
  8. data/apps/core/admin/public/sass/admin.scss +6 -1
  9. data/apps/core/components/widgets/crud/crud.shtml +2 -2
  10. data/apps/core/components/widgets/table/table.rb +5 -5
  11. data/apps/core/forms/tags/element_row.erb +15 -10
  12. data/apps/core/forms/widgets/form/form.rb +35 -22
  13. data/apps/core/forms/widgets/inputs/checkbox/checkbox.shtml +2 -2
  14. data/apps/core/forms/widgets/inputs/date_time/date_time.shtml +2 -2
  15. data/apps/core/forms/widgets/inputs/file_input/file_input.shtml +2 -2
  16. data/apps/core/forms/widgets/inputs/html_area/html_area.shtml +2 -2
  17. data/apps/core/forms/widgets/inputs/input/input.shtml +2 -2
  18. data/apps/core/forms/widgets/inputs/password/password.shtml +2 -2
  19. data/apps/core/forms/widgets/inputs/search_select/search_select.shtml +1 -1
  20. data/apps/core/forms/widgets/inputs/select/select.shtml +2 -2
  21. data/apps/core/forms/widgets/inputs/text/text.shtml +2 -2
  22. data/apps/core/forms/widgets/inputs/text_area/text_area.shtml +2 -2
  23. data/apps/core/forms/widgets/inputs/time_span/time_span.shtml +1 -1
  24. data/blueprints/home/config.ru +8 -0
  25. data/lib/spiderfw/app.rb +416 -224
  26. data/lib/spiderfw/cmd/commands/app.rb +243 -239
  27. data/lib/spiderfw/cmd/commands/cert.rb +421 -417
  28. data/lib/spiderfw/cmd/commands/config.rb +85 -82
  29. data/lib/spiderfw/cmd/commands/console.rb +64 -40
  30. data/lib/spiderfw/cmd/commands/content.rb +29 -25
  31. data/lib/spiderfw/cmd/commands/create.rb +58 -54
  32. data/lib/spiderfw/cmd/commands/model.rb +118 -114
  33. data/lib/spiderfw/cmd/commands/setup.rb +55 -51
  34. data/lib/spiderfw/cmd/commands/test.rb +63 -59
  35. data/lib/spiderfw/cmd/commands/webserver.rb +56 -51
  36. data/lib/spiderfw/config/options/spider.rb +4 -3
  37. data/lib/spiderfw/controller/controller.rb +2 -0
  38. data/lib/spiderfw/controller/http_controller.rb +1 -2
  39. data/lib/spiderfw/controller/mixins/static_content.rb +3 -3
  40. data/lib/spiderfw/controller/mixins/visual.rb +30 -15
  41. data/lib/spiderfw/controller/response.rb +84 -0
  42. data/lib/spiderfw/controller/session/file_session.rb +2 -2
  43. data/lib/spiderfw/http/adapters/rack.rb +12 -13
  44. data/lib/spiderfw/http/server.rb +80 -46
  45. data/lib/spiderfw/i18n/cldr.rb +6 -9
  46. data/lib/spiderfw/model/base_model.rb +103 -23
  47. data/lib/spiderfw/model/condition.rb +110 -25
  48. data/lib/spiderfw/model/mappers/db_mapper.rb +14 -6
  49. data/lib/spiderfw/model/mappers/mapper.rb +440 -197
  50. data/lib/spiderfw/model/model.rb +105 -21
  51. data/lib/spiderfw/model/model_hash.rb +9 -1
  52. data/lib/spiderfw/model/query.rb +50 -9
  53. data/lib/spiderfw/model/query_set.rb +211 -44
  54. data/lib/spiderfw/model/request.rb +28 -21
  55. data/lib/spiderfw/model/storage/base_storage.rb +125 -10
  56. data/lib/spiderfw/model/storage/db/db_storage.rb +7 -4
  57. data/lib/spiderfw/model/storage.rb +8 -1
  58. data/lib/spiderfw/setup/spider_setup_wizard.rb +9 -7
  59. data/lib/spiderfw/spider.rb +270 -43
  60. data/lib/spiderfw/templates/layout.rb +9 -4
  61. data/lib/spiderfw/templates/resources/sass.rb +3 -2
  62. data/lib/spiderfw/templates/template.rb +1 -0
  63. data/lib/spiderfw/utils/annotations.rb +3 -1
  64. data/lib/spiderfw/utils/logger.rb +1 -1
  65. data/lib/spiderfw/utils/monkey/symbol.rb +4 -2
  66. data/lib/spiderfw/utils/shared_store/file_shared_store.rb +2 -2
  67. data/lib/spiderfw/utils/thread_out.rb +3 -1
  68. data/public/css/error_page.css +83 -0
  69. data/public/js/error_page.js +5 -0
  70. data/spider.gemspec +4 -1
  71. data/templates/email/error.erb +9 -0
  72. metadata +28 -12
  73. data/apps/config_editor/widgets/edit_bool/edit_bool.rb +0 -8
  74. data/apps/config_editor/widgets/edit_bool/edit_bool.shtml +0 -5
@@ -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
- # Base types are:
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. Will walk superclasses and DataType info until
24
- # a base type is found.
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
- # TODO: remove?
34
- def self.ruby_type(klass) #:nodoc:
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
- def self.simplify_type(klass) #:nodoc:
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
- # Returns the identity-mapped object
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
- def self.identity_mapper #:nodoc:
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
- def self.identity_mapper=(im) #:nodoc:
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
- def self.unit_of_work(&proc) #:nodoc:
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 the block in the context of the main IdentityMapper.
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
- # FIXME: this is clearly db specific. Move somewhere else.
178
- def self.sync_schema(model_or_app, force=false, options={}) #:nodoc:
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
- attr_reader :element, :value
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
- alias :modelhash_orig_set :[]= # :nodoc:
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)
@@ -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
- def first
131
- self.limit = 1
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
- def polymorphs? # :nodoc:
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