spiderfw 0.6.23 → 0.6.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +10 -1
- data/README.rdoc +1 -1
- data/VERSION +1 -1
- data/apps/config_editor/_init.rb +1 -2
- data/apps/config_editor/controllers/config_editor_controller.rb +1 -7
- data/apps/core/admin/controllers/admin_controller.rb +1 -1
- data/apps/core/admin/public/css/sass/admin.css +35 -31
- data/apps/core/admin/public/sass/admin.scss +6 -1
- data/apps/core/components/widgets/crud/crud.shtml +2 -2
- data/apps/core/components/widgets/table/table.rb +5 -5
- data/apps/core/forms/tags/element_row.erb +15 -10
- data/apps/core/forms/widgets/form/form.rb +35 -22
- data/apps/core/forms/widgets/inputs/checkbox/checkbox.shtml +2 -2
- data/apps/core/forms/widgets/inputs/date_time/date_time.shtml +2 -2
- data/apps/core/forms/widgets/inputs/file_input/file_input.shtml +2 -2
- data/apps/core/forms/widgets/inputs/html_area/html_area.shtml +2 -2
- data/apps/core/forms/widgets/inputs/input/input.shtml +2 -2
- data/apps/core/forms/widgets/inputs/password/password.shtml +2 -2
- data/apps/core/forms/widgets/inputs/search_select/search_select.shtml +1 -1
- data/apps/core/forms/widgets/inputs/select/select.shtml +2 -2
- data/apps/core/forms/widgets/inputs/text/text.shtml +2 -2
- data/apps/core/forms/widgets/inputs/text_area/text_area.shtml +2 -2
- data/apps/core/forms/widgets/inputs/time_span/time_span.shtml +1 -1
- data/blueprints/home/config.ru +8 -0
- data/lib/spiderfw/app.rb +416 -224
- data/lib/spiderfw/cmd/commands/app.rb +243 -239
- data/lib/spiderfw/cmd/commands/cert.rb +421 -417
- data/lib/spiderfw/cmd/commands/config.rb +85 -82
- data/lib/spiderfw/cmd/commands/console.rb +64 -40
- data/lib/spiderfw/cmd/commands/content.rb +29 -25
- data/lib/spiderfw/cmd/commands/create.rb +58 -54
- data/lib/spiderfw/cmd/commands/model.rb +118 -114
- data/lib/spiderfw/cmd/commands/setup.rb +55 -51
- data/lib/spiderfw/cmd/commands/test.rb +63 -59
- data/lib/spiderfw/cmd/commands/webserver.rb +56 -51
- data/lib/spiderfw/config/options/spider.rb +4 -3
- data/lib/spiderfw/controller/controller.rb +2 -0
- data/lib/spiderfw/controller/http_controller.rb +1 -2
- data/lib/spiderfw/controller/mixins/static_content.rb +3 -3
- data/lib/spiderfw/controller/mixins/visual.rb +30 -15
- data/lib/spiderfw/controller/response.rb +84 -0
- data/lib/spiderfw/controller/session/file_session.rb +2 -2
- data/lib/spiderfw/http/adapters/rack.rb +12 -13
- data/lib/spiderfw/http/server.rb +80 -46
- data/lib/spiderfw/i18n/cldr.rb +6 -9
- data/lib/spiderfw/model/base_model.rb +103 -23
- data/lib/spiderfw/model/condition.rb +110 -25
- data/lib/spiderfw/model/mappers/db_mapper.rb +14 -6
- data/lib/spiderfw/model/mappers/mapper.rb +440 -197
- data/lib/spiderfw/model/model.rb +105 -21
- data/lib/spiderfw/model/model_hash.rb +9 -1
- data/lib/spiderfw/model/query.rb +50 -9
- data/lib/spiderfw/model/query_set.rb +211 -44
- data/lib/spiderfw/model/request.rb +28 -21
- data/lib/spiderfw/model/storage/base_storage.rb +125 -10
- data/lib/spiderfw/model/storage/db/db_storage.rb +7 -4
- data/lib/spiderfw/model/storage.rb +8 -1
- data/lib/spiderfw/setup/spider_setup_wizard.rb +9 -7
- data/lib/spiderfw/spider.rb +270 -43
- data/lib/spiderfw/templates/layout.rb +9 -4
- data/lib/spiderfw/templates/resources/sass.rb +3 -2
- data/lib/spiderfw/templates/template.rb +1 -0
- data/lib/spiderfw/utils/annotations.rb +3 -1
- data/lib/spiderfw/utils/logger.rb +1 -1
- data/lib/spiderfw/utils/monkey/symbol.rb +4 -2
- data/lib/spiderfw/utils/shared_store/file_shared_store.rb +2 -2
- data/lib/spiderfw/utils/thread_out.rb +3 -1
- data/public/css/error_page.css +83 -0
- data/public/js/error_page.js +5 -0
- data/spider.gemspec +4 -1
- data/templates/email/error.erb +9 -0
- metadata +28 -12
- data/apps/config_editor/widgets/edit_bool/edit_bool.rb +0 -8
- data/apps/config_editor/widgets/edit_bool/edit_bool.shtml +0 -5
@@ -2,32 +2,46 @@ require 'spiderfw/model/model_hash'
|
|
2
2
|
|
3
3
|
module Spider; module Model
|
4
4
|
|
5
|
-
# The Condition behaves like a ModelHash, and as such contains key-value pairs:
|
5
|
+
# The Condition behaves like a {ModelHash}, and as such contains key-value pairs:
|
6
6
|
# a simple equality condition can be set with
|
7
7
|
# condition[:element_name] = value
|
8
8
|
# The Condition object also holds comparisons: a comparison different from equality can be set with
|
9
9
|
# condition.set(:element_name, '>', value)
|
10
10
|
# Finally, it contains subconditions, which can be added with
|
11
11
|
# conditions << subcondition
|
12
|
-
# Subconditions will be created automatically when using #set twice on the same element.
|
13
|
-
# If you want to change the condition, use #delete and set it again.
|
12
|
+
# Subconditions will be created automatically when using {#set} twice on the same element.
|
13
|
+
# If you want to change the condition, use {#delete} and set it again.
|
14
|
+
#
|
15
|
+
# Conditions also support an SQL-like block syntax for setting conditions:
|
16
|
+
# books_condition = Condition.new{ |book|
|
17
|
+
# ((book.year < 1970) | (book.price > 1000)) & (book.author.name .like 'John')
|
18
|
+
# }
|
14
19
|
#
|
15
20
|
# The Condition object, like the Request, doesn't hold a reference to a model; so no check will be made
|
16
21
|
# that the conditions elements are meaningful.
|
17
22
|
|
18
23
|
class Condition < Hash
|
19
24
|
# The top level conjunction for the Condition (:or or :and; new Conditions are initialized with :or)
|
25
|
+
# @return [Symbol] :and | :or
|
20
26
|
attr_accessor :conjunction
|
21
27
|
# Polymorph model: used to tell the mapper the condition is on a subclass of the queried model.
|
28
|
+
# @return [Class<BaseModel]
|
22
29
|
attr_accessor :polymorph
|
23
30
|
# An hash of comparisons for each element name
|
31
|
+
# @return [Hash]
|
24
32
|
attr_reader :comparisons
|
25
33
|
# An Array of subconditions
|
34
|
+
# @return [Array]
|
26
35
|
attr_reader :subconditions
|
27
|
-
|
36
|
+
# @private
|
37
|
+
# A pointer to the last Condition used in condition blocks
|
38
|
+
# @return [Condition]
|
39
|
+
attr_accessor :conjunct
|
40
|
+
# Original hash value assignment
|
28
41
|
alias :hash_set :[]= # :nodoc:
|
29
42
|
|
30
43
|
# See #ModelHash.get_deep_obj
|
44
|
+
# @return [Condition]
|
31
45
|
def get_deep_obj # :nodoc:
|
32
46
|
c = self.class.new
|
33
47
|
c.conjunction = @conjunction
|
@@ -40,12 +54,18 @@ module Spider; module Model
|
|
40
54
|
str += Regexp.quote(op)
|
41
55
|
end
|
42
56
|
|
57
|
+
# @private
|
43
58
|
# Regexp to parse comparison operators
|
44
|
-
|
59
|
+
# @return [Regexp]
|
60
|
+
def self.comparison_operators_regexp
|
45
61
|
@comparison_operators_regexp
|
46
62
|
end
|
47
63
|
|
48
|
-
#
|
64
|
+
# @private
|
65
|
+
# Used by {Condition.and} and {Condition.or} methods
|
66
|
+
# @param [Symbol] conjunction
|
67
|
+
# @param [Condition] a
|
68
|
+
# @param [Condition] b
|
49
69
|
def self.conj(conjunction, a, b) # :nodoc:
|
50
70
|
c = Condition.new
|
51
71
|
c.conjunction = conjunction
|
@@ -54,7 +74,8 @@ module Spider; module Model
|
|
54
74
|
end
|
55
75
|
|
56
76
|
# Instantiates a Condition with :and conjunction.
|
57
|
-
# See
|
77
|
+
# See {Condition.new} for arguments.
|
78
|
+
# @return [Condition]
|
58
79
|
def self.and(*params, &proc)
|
59
80
|
c = self.new(*params, &proc)
|
60
81
|
c.conjunction = :and
|
@@ -62,7 +83,8 @@ module Spider; module Model
|
|
62
83
|
end
|
63
84
|
|
64
85
|
# Instantiates a Condition with :or conjunction.
|
65
|
-
# See
|
86
|
+
# See {Condition.new} for arguments.
|
87
|
+
# @return [Condition]
|
66
88
|
def self.or(*params, &proc)
|
67
89
|
c = self.new(*params, &proc)
|
68
90
|
c.conjunction = :or
|
@@ -70,7 +92,9 @@ module Spider; module Model
|
|
70
92
|
end
|
71
93
|
|
72
94
|
# Instantiates a Condition with no conjunction.
|
73
|
-
|
95
|
+
# See {Condition.new} for arguments.
|
96
|
+
# @return [Condition]
|
97
|
+
def self.no_conjunction(*params, &proc)
|
74
98
|
c = self.new(*params, &proc)
|
75
99
|
c.conjunction = nil
|
76
100
|
return c
|
@@ -101,12 +125,14 @@ module Spider; module Model
|
|
101
125
|
#
|
102
126
|
# Example:
|
103
127
|
# condition.parse_block{ (element1 == val1) & ( (element2 > 'some string') | (element3 .not nil) ) }
|
128
|
+
#
|
104
129
|
# All comparisons must be parenthesized; and/or conjunctions are expressed with a single &/|.
|
105
130
|
#
|
106
131
|
# Available comparisions are: ==, >, <, >=, <=, .not, .like, .ilike (case insensitive like).
|
107
132
|
#
|
108
133
|
# _Note:_ for .like and .ilike comparisons, the SQL '%' syntax must be used.
|
109
134
|
#
|
135
|
+
# @param [Proc] proc The condition block
|
110
136
|
def parse_block(&proc)
|
111
137
|
res = nil
|
112
138
|
if proc.arity == 1
|
@@ -122,6 +148,7 @@ module Spider; module Model
|
|
122
148
|
@polymorph = res.polymorph
|
123
149
|
end
|
124
150
|
|
151
|
+
# @return [Array] An array of all conditions, expressed as [key, value, comparison]
|
125
152
|
def conditions_array
|
126
153
|
self.hash_clone.map do |k, v|
|
127
154
|
k = k.to_sym if k.respond_to?(:to_sym)
|
@@ -130,6 +157,7 @@ module Spider; module Model
|
|
130
157
|
end
|
131
158
|
|
132
159
|
# Yields each key, value and comparison.
|
160
|
+
# @return void
|
133
161
|
def each_with_comparison
|
134
162
|
self.each do |k, v|
|
135
163
|
k = k.to_sym if k.respond_to?(:to_sym)
|
@@ -138,6 +166,7 @@ module Spider; module Model
|
|
138
166
|
end
|
139
167
|
|
140
168
|
# Yields each key, value and comparison, for this condition and its subconditions
|
169
|
+
# @return [void]
|
141
170
|
def all_each_with_comparison
|
142
171
|
self.each_with_comparison{ |k, v, c| yield k, v, c }
|
143
172
|
@subconditions.each do |sub|
|
@@ -145,11 +174,15 @@ module Spider; module Model
|
|
145
174
|
end
|
146
175
|
end
|
147
176
|
|
177
|
+
# @param [Class<BaseModel] The model on which the Condition is based on.
|
178
|
+
# @return [bool] True if the condition has only primary keys for the given model
|
148
179
|
def primary_keys_only?(model)
|
149
180
|
self.select{ |key, value| !model.elements[key] || !model.elements[key].primary_key? }.empty?
|
150
181
|
end
|
151
182
|
|
152
183
|
# Returns the result of merging the condition with another one (does not modify the original condition).
|
184
|
+
# @param [Condition] Condition to merge with
|
185
|
+
# @return [Condition] The resulting Condition
|
153
186
|
def +(condition)
|
154
187
|
res = self.clone
|
155
188
|
@subconditions += condition.subconditions
|
@@ -160,6 +193,8 @@ module Spider; module Model
|
|
160
193
|
end
|
161
194
|
|
162
195
|
# Adds a subcondtion.
|
196
|
+
# @param [Condition] condition
|
197
|
+
# @return [void]
|
163
198
|
def <<(condition)
|
164
199
|
if (condition.class == self.class)
|
165
200
|
@subconditions << condition
|
@@ -171,7 +206,11 @@ module Spider; module Model
|
|
171
206
|
end
|
172
207
|
end
|
173
208
|
|
174
|
-
#
|
209
|
+
# Adds a single condition for an element
|
210
|
+
# @param [Symbol|String|QueryFuncs::Function] field to add the condition to
|
211
|
+
# @param [String] comparison: can be =, <, >, <=, >=, 'between'
|
212
|
+
# @param [QuerySet|Array|Range|Object] the value of the condition
|
213
|
+
# @return [self]
|
175
214
|
def set(field, comparison, value)
|
176
215
|
if value.is_a?(QuerySet)
|
177
216
|
value = value.to_a
|
@@ -188,6 +227,7 @@ module Spider; module Model
|
|
188
227
|
unless field.is_a?(Spider::QueryFuncs::Function)
|
189
228
|
field = field.to_s
|
190
229
|
parts = field.split('.', 2)
|
230
|
+
debugger if parts[0].blank?
|
191
231
|
parts[0] = parts[0].to_sym
|
192
232
|
field = field.to_sym unless parts[1]
|
193
233
|
end
|
@@ -206,10 +246,18 @@ module Spider; module Model
|
|
206
246
|
end
|
207
247
|
|
208
248
|
# Sets an equality comparison.
|
249
|
+
#
|
250
|
+
# Equivalent to {#set}(key, '=', value)
|
251
|
+
# @param [String|Symbol|QueryFuncs::Function] key
|
252
|
+
# @param [Object] value
|
253
|
+
# @return [self]
|
209
254
|
def []=(key, value)
|
210
255
|
set(key, '=', value)
|
211
256
|
end
|
212
257
|
|
258
|
+
# Gets the value of a condition
|
259
|
+
# @param [String|Symbol|QueryFuncs::Function] key
|
260
|
+
# @return [Object] value
|
213
261
|
def [](key)
|
214
262
|
# TODO: deep
|
215
263
|
key = key.name if key.is_a?(Element)
|
@@ -218,6 +266,10 @@ module Spider; module Model
|
|
218
266
|
end
|
219
267
|
|
220
268
|
# Adds a range condition. This creates a subcondition with >= and <= conditions.
|
269
|
+
# @param [String|Symbol|QueryFuncs::Function] key
|
270
|
+
# @param [Object] lower
|
271
|
+
# @param [Object] upper
|
272
|
+
# @return [self]
|
221
273
|
def range(field, lower, upper)
|
222
274
|
c = self.class.and
|
223
275
|
c.set(field, '>=', lower)
|
@@ -226,6 +278,8 @@ module Spider; module Model
|
|
226
278
|
end
|
227
279
|
|
228
280
|
# Deletes a field from the Condition.
|
281
|
+
# @param [String|Symbol|QueryFuncs::Function] key
|
282
|
+
# @return [Array] A pair containing the deleted value and comparison
|
229
283
|
def delete(field)
|
230
284
|
field = field.to_sym
|
231
285
|
return nil unless self[field] || @comparisons[field]
|
@@ -235,17 +289,7 @@ module Spider; module Model
|
|
235
289
|
cur
|
236
290
|
end
|
237
291
|
|
238
|
-
#
|
239
|
-
# TODO: remove?
|
240
|
-
def parse_comparison(comparison) # :nodoc:
|
241
|
-
if (comparison =~ Regexp.new("(.+)(#{self.class.comparison_operators_regexp})(.+)"))
|
242
|
-
val = $3.strip
|
243
|
-
# strip single and double quotes
|
244
|
-
val = val[1..-2] if ((val[0] == ?' && val[-1] == ?') || (val[0] == ?" && val[-1] == ?") )
|
245
|
-
return [$1.strip, $2.strip, val]
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
292
|
+
# @return [String] A String representation of the condition
|
249
293
|
def inspect
|
250
294
|
str = ""
|
251
295
|
cnt = 0
|
@@ -269,6 +313,10 @@ module Spider; module Model
|
|
269
313
|
# Returns the conjunction with another condition.
|
270
314
|
# If this condition already has the required conjunction, the other will be added as a subcondition;
|
271
315
|
# otherwise, a new condition will be created and both will be added to it.
|
316
|
+
# @param [Symbol] conjunction :and | :or
|
317
|
+
# @param [Condition] other Condition to conjuct to this
|
318
|
+
# @param [Proc] proc Block to create the other condition
|
319
|
+
# @return [Condition] The resulting Condition (self, or the new Condition created)
|
272
320
|
def conj(conjunction, other=nil, &proc)
|
273
321
|
self.conjunction = conjunction if (!self.conjunction)
|
274
322
|
if (self.conjunction == conjunction)
|
@@ -287,14 +335,20 @@ module Spider; module Model
|
|
287
335
|
end
|
288
336
|
|
289
337
|
|
290
|
-
# Joins the condition to another with an "or" conjunction. See #conj.
|
338
|
+
# Joins the condition to another with an "or" conjunction. See {#conj}.
|
339
|
+
# @param [Condition] other Condition to conjuct to this
|
340
|
+
# @param [Proc] proc Block to create the other condition
|
341
|
+
# @return [Condition] The resulting Condition (self, or the new Condition created)
|
291
342
|
def or(other=nil, &proc)
|
292
343
|
return conj(:or, other, &proc)
|
293
344
|
end
|
294
345
|
alias :| :or
|
295
346
|
alias :OR :or
|
296
347
|
|
297
|
-
# Joins the condition to another with an "and" conjunction. See #conj.
|
348
|
+
# Joins the condition to another with an "and" conjunction. See {#conj}.
|
349
|
+
# @param [Condition] other Condition to conjuct to this
|
350
|
+
# @param [Proc] proc Block to create the other condition
|
351
|
+
# @return [Condition] The resulting Condition (self, or the new Condition created)
|
298
352
|
def and(other=nil, &proc)
|
299
353
|
return conj(:and, other, &proc)
|
300
354
|
end
|
@@ -304,6 +358,7 @@ module Spider; module Model
|
|
304
358
|
alias :hash_empty? :empty? # :nodoc:
|
305
359
|
|
306
360
|
# True if there are no comparisons and no subconditions.
|
361
|
+
# @return [bool] True if the Condition is empty, false otherwise
|
307
362
|
def empty?
|
308
363
|
return false unless super
|
309
364
|
@subconditions.each do |sub|
|
@@ -312,17 +367,23 @@ module Spider; module Model
|
|
312
367
|
return true
|
313
368
|
end
|
314
369
|
|
315
|
-
|
370
|
+
# Alias to the original Hash#replace
|
371
|
+
alias :hash_replace :replace
|
316
372
|
|
317
|
-
# Replace the content of this Condition with another one.
|
373
|
+
# Replace all the content of this Condition with another one.
|
374
|
+
# @param [Condition] other The other condition
|
375
|
+
# @return [self]
|
318
376
|
def replace(other)
|
319
377
|
hash_replace(other)
|
320
378
|
@subconditions = other.subconditions
|
321
379
|
@conjunction = other.conjunction
|
322
380
|
@polymorph = other.polymorph
|
323
381
|
@comparisons = other.comparisons
|
382
|
+
self
|
324
383
|
end
|
325
384
|
|
385
|
+
# @param [Condition] other
|
386
|
+
# @return [bool] True if the two conditions have the same comparisions and conjunction
|
326
387
|
def ==(other)
|
327
388
|
return false unless other.class == self.class
|
328
389
|
return false unless super
|
@@ -333,22 +394,28 @@ module Spider; module Model
|
|
333
394
|
return true
|
334
395
|
end
|
335
396
|
|
397
|
+
# @return [bool] See {#==}
|
336
398
|
def eql?(other)
|
337
399
|
self == other
|
338
400
|
end
|
339
401
|
|
402
|
+
# @return [String] Keying hash
|
340
403
|
def hash
|
341
404
|
([self.keys, self.values, @comparisons.values, @polymorph] + @subconditions.map{ |s| s.hash}).hash
|
342
405
|
end
|
343
406
|
|
344
407
|
# Removes duplicate subcondtions.
|
408
|
+
# @return self
|
345
409
|
def uniq!
|
346
410
|
@subconditions.uniq!
|
411
|
+
self
|
347
412
|
end
|
348
413
|
|
414
|
+
# Alias for Hash#clone
|
349
415
|
alias :hash_clone :clone
|
350
416
|
|
351
417
|
# Returns a deep copy.
|
418
|
+
# @return [Condition] A copy of this Condition
|
352
419
|
def clone
|
353
420
|
c = self.class.new
|
354
421
|
c.conjunction = @conjunction
|
@@ -363,6 +430,7 @@ module Spider; module Model
|
|
363
430
|
end
|
364
431
|
|
365
432
|
# Traverses the tree removing useless conditions.
|
433
|
+
# @return [self]
|
366
434
|
def simplify
|
367
435
|
@subconditions.each{ |sub| sub.simplify }
|
368
436
|
if (hash_empty? && @subconditions.length == 1)
|
@@ -372,6 +440,7 @@ module Spider; module Model
|
|
372
440
|
return self
|
373
441
|
end
|
374
442
|
|
443
|
+
# @return [Array] An array of polymorphic conditions
|
375
444
|
def polymorphs
|
376
445
|
pol = []
|
377
446
|
pol << @polymorph if @polymorph
|
@@ -379,6 +448,8 @@ module Spider; module Model
|
|
379
448
|
end
|
380
449
|
|
381
450
|
# Returns, from self and subconditions, all those who define a condition for one of the given element names.
|
451
|
+
# @param [*Symbol] element_names A list of element names
|
452
|
+
# @return [Array] An array of matching conditions
|
382
453
|
def conditions_for(*element_names)
|
383
454
|
conds = []
|
384
455
|
element_names.each do |el|
|
@@ -390,9 +461,23 @@ module Spider; module Model
|
|
390
461
|
@subconditions.map{ |s| s.conditions_for(*element_names) }.each{ |c| conds += c }
|
391
462
|
conds
|
392
463
|
end
|
464
|
+
|
465
|
+
private
|
466
|
+
|
467
|
+
# Parses a string comparison.
|
468
|
+
# TODO: remove?
|
469
|
+
def parse_comparison(comparison) # :nodoc:
|
470
|
+
if (comparison =~ Regexp.new("(.+)(#{self.class.comparison_operators_regexp})(.+)"))
|
471
|
+
val = $3.strip
|
472
|
+
# strip single and double quotes
|
473
|
+
val = val[1..-2] if ((val[0] == ?' && val[-1] == ?') || (val[0] == ?" && val[-1] == ?") )
|
474
|
+
return [$1.strip, $2.strip, val]
|
475
|
+
end
|
476
|
+
end
|
393
477
|
|
394
478
|
end
|
395
479
|
|
480
|
+
# Helper module used for Condition block syntax
|
396
481
|
module ConditionMixin # :nodoc:
|
397
482
|
|
398
483
|
def __el(meth)
|
@@ -4,15 +4,20 @@ require 'fileutils'
|
|
4
4
|
|
5
5
|
module Spider; module Model; module Mappers
|
6
6
|
|
7
|
+
# This is the Mapper subclass for interacting with databases.
|
7
8
|
class DbMapper < Spider::Model::Mapper
|
8
9
|
include Spider::Model::Storage::Db
|
9
10
|
|
11
|
+
# @param [BaseModel] model
|
12
|
+
# @param [Storage]
|
10
13
|
def initialize(model, storage)
|
11
14
|
super
|
12
15
|
@type = :db
|
13
16
|
end
|
14
17
|
|
15
|
-
|
18
|
+
# Is this mapper writable?
|
19
|
+
# @return [true]
|
20
|
+
def self.write?
|
16
21
|
true
|
17
22
|
end
|
18
23
|
|
@@ -797,7 +802,10 @@ module Spider; module Model; module Mappers
|
|
797
802
|
# * joins
|
798
803
|
# * final model called
|
799
804
|
# * final element called
|
800
|
-
|
805
|
+
# @param [String] dotted_element: the element to get joins for
|
806
|
+
# @param [Symbol] join_type (nil, :inner, :left, :right, :outer): force a join type for all elements
|
807
|
+
# @return [Array] [joins, final_model, final_element]
|
808
|
+
def get_deep_join(dotted_element, join_type=nil)
|
801
809
|
#return [[], @model, @model.elements[dotted_element]] unless dotted_element.is_a?(String)
|
802
810
|
parts = dotted_element.to_s.split('.').map{ |el| el.to_sym }
|
803
811
|
current_model = @model
|
@@ -811,17 +819,17 @@ module Spider; module Model; module Mappers
|
|
811
819
|
raise "Can't find element #{part} in model #{current_model}" unless el
|
812
820
|
next if have_references?(el) && cnt == parts.length
|
813
821
|
if el.integrated?
|
814
|
-
joins << current_model.mapper.get_join(el.integrated_from)
|
822
|
+
joins << current_model.mapper.get_join(el.integrated_from, join_type)
|
815
823
|
current_model = el.integrated_from.type
|
816
824
|
el = current_model.elements[el.integrated_from_element]
|
817
825
|
end
|
818
826
|
if el.model? && can_join?(el)
|
819
|
-
joins << current_model.mapper.get_join(el)
|
827
|
+
joins << current_model.mapper.get_join(el, join_type)
|
820
828
|
current_model = el.model
|
821
829
|
end
|
822
830
|
end
|
823
831
|
while el.integrated? && !have_references?(el)
|
824
|
-
joins << current_model.mapper.get_join(el.integrated_from)
|
832
|
+
joins << current_model.mapper.get_join(el.integrated_from, join_type)
|
825
833
|
# joins << current_model.integrated_from.mapper.get_join(el.integrated_from_element)
|
826
834
|
current_model = el.integrated_from.type
|
827
835
|
el = current_model.elements[el.integrated_from_element]
|
@@ -871,7 +879,7 @@ module Spider; module Model; module Mappers
|
|
871
879
|
joins += field.joins
|
872
880
|
fields << [field, direction]
|
873
881
|
else
|
874
|
-
el_joins, el_model, el = get_deep_join(order_element)
|
882
|
+
el_joins, el_model, el = get_deep_join(order_element, :left)
|
875
883
|
if el.model?
|
876
884
|
if el_model.mapper.have_references?(el) || el.model.storage != storage
|
877
885
|
el.model.primary_keys.each do |pk|
|