dm-persevere-adapter 0.71.4 → 0.72.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +16 -0
- data/README.txt +1 -1
- data/Rakefile +17 -3
- data/VERSION +1 -1
- data/lib/persevere_adapter.rb +13 -778
- data/lib/persevere_adapter/adapter.rb +544 -0
- data/lib/persevere_adapter/aggregates.rb +75 -0
- data/lib/persevere_adapter/enhance.rb +49 -0
- data/lib/persevere_adapter/json_support.rb +6 -0
- data/lib/persevere_adapter/json_support/core.rb +17 -0
- data/lib/persevere_adapter/json_support/model.rb +22 -0
- data/lib/persevere_adapter/json_support/model/properties.rb +23 -0
- data/lib/persevere_adapter/json_support/property.rb +23 -0
- data/lib/persevere_adapter/json_support/resource.rb +37 -0
- data/lib/persevere_adapter/migrations.rb +104 -0
- data/lib/persevere_adapter/query.rb +208 -0
- data/lib/persevere_adapter/support/big_decimal.rb +10 -0
- data/lib/{persevere.rb → persevere_client.rb} +2 -2
- data/spec/persevere_adapter_spec.rb +508 -488
- data/spec/persevere_client_spec.rb +202 -0
- data/spec/spec_helper.rb +12 -3
- data/tasks/spec.rake +0 -1
- metadata +159 -24
- data/lib/dm/associations/many_to_many.rb +0 -278
- data/lib/dm/associations/relationship.rb +0 -57
- data/lib/dm/model.rb +0 -29
- data/lib/dm/property.rb +0 -25
- data/lib/dm/query.rb +0 -174
- data/lib/dm/resource.rb +0 -102
- data/spec/persevere_spec.rb +0 -201
@@ -1,278 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Associations
|
3
|
-
module ManyToMany #:nodoc:
|
4
|
-
class Relationship < Associations::OneToMany::Relationship
|
5
|
-
|
6
|
-
OPTIONS.delete(:via)
|
7
|
-
OPTIONS.delete(:through)
|
8
|
-
|
9
|
-
remove_method :through
|
10
|
-
remove_method :via
|
11
|
-
remove_method :lazy_load
|
12
|
-
remove_method :source_scope
|
13
|
-
remove_method :inverted_options
|
14
|
-
remove_method :valid_target?
|
15
|
-
remove_method :valid_source?
|
16
|
-
|
17
|
-
#
|
18
|
-
# @api private
|
19
|
-
def query
|
20
|
-
@query
|
21
|
-
end
|
22
|
-
|
23
|
-
def set(source, target)
|
24
|
-
assert_kind_of 'source', source, source_model
|
25
|
-
assert_kind_of 'target', target, Array
|
26
|
-
target.each {|item| assert_kind_of 'target array element', item, target_model }
|
27
|
-
lazy_load(source) unless loaded?(source)
|
28
|
-
# NOTE: This seems semantically wrong, a set should just erase the contents,
|
29
|
-
# not calculate the difference and replace the common elements...
|
30
|
-
get!(source).replace(target)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Loads association targets and sets resulting value on
|
34
|
-
# given source resource
|
35
|
-
#
|
36
|
-
# @param [Resource] source
|
37
|
-
# the source resource for the association
|
38
|
-
#
|
39
|
-
# @return [undefined]
|
40
|
-
#
|
41
|
-
# @api private
|
42
|
-
def lazy_load(source)
|
43
|
-
|
44
|
-
# SEL: load all related resources in the source collection
|
45
|
-
collection = source.collection
|
46
|
-
|
47
|
-
# if source.saved? && collection.size > 1 #OLD LINE --IRJ
|
48
|
-
if source.saved?
|
49
|
-
eager_load(collection)
|
50
|
-
end
|
51
|
-
|
52
|
-
unless loaded?(source)
|
53
|
-
set!(source, collection_for(source))
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Eager load the collection using the source as a base
|
58
|
-
#
|
59
|
-
# @param [Collection] source
|
60
|
-
# the source collection to query with
|
61
|
-
# @param [Query, Hash] query
|
62
|
-
# optional query to restrict the collection
|
63
|
-
#
|
64
|
-
# @return [Collection]
|
65
|
-
# the loaded collection for the source
|
66
|
-
#
|
67
|
-
# @api private
|
68
|
-
def eager_load(source, query = nil)
|
69
|
-
|
70
|
-
targets = source.model.all(query_for(source, query))
|
71
|
-
|
72
|
-
# FIXME: cannot associate targets to m:m collection yet, maybe we fixed it.
|
73
|
-
# if source.loaded? && !source.kind_of?(ManyToMany::Collection) WE CHANGED THIS: IRJ/RL
|
74
|
-
if source.loaded?
|
75
|
-
associate_targets(source, targets)
|
76
|
-
end
|
77
|
-
|
78
|
-
targets
|
79
|
-
end
|
80
|
-
|
81
|
-
def associate_targets(source, targets)
|
82
|
-
# TODO: create an object that wraps this logic, and when the first
|
83
|
-
# kicker is fired, then it'll load up the collection, and then
|
84
|
-
# populate all the other methods
|
85
|
-
target_maps = Hash.new { |hash, key| hash[key] = [] }
|
86
|
-
|
87
|
-
targets.each do |target|
|
88
|
-
target_maps[target_key.get(target)] << target
|
89
|
-
end
|
90
|
-
|
91
|
-
Array(source).each do |source|
|
92
|
-
key = source_key.get(source)
|
93
|
-
# eager_load_targets(source, target_maps[key], query)
|
94
|
-
|
95
|
-
set!(source, collection_for(source, query).set(targets))
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
private
|
100
|
-
|
101
|
-
# Returns the inverse relationship class
|
102
|
-
#
|
103
|
-
# @api private
|
104
|
-
def inverse_class
|
105
|
-
self.class
|
106
|
-
end
|
107
|
-
|
108
|
-
def inverse_name
|
109
|
-
self.prefix = "" if self.prefix.nil?
|
110
|
-
(self.prefix + Extlib::Inflection.underscore(Extlib::Inflection.demodulize(source_model.name)).pluralize).to_sym
|
111
|
-
end
|
112
|
-
|
113
|
-
# @api private
|
114
|
-
def invert
|
115
|
-
inverse_class.new(inverse_name, parent_model, child_model, inverted_options)
|
116
|
-
end
|
117
|
-
|
118
|
-
# @api semipublic
|
119
|
-
def initialize(name, target_model, source_model, options = {})
|
120
|
-
options.delete(:through)
|
121
|
-
super
|
122
|
-
end
|
123
|
-
|
124
|
-
# Returns collection class used by this type of
|
125
|
-
# relationship
|
126
|
-
#
|
127
|
-
# @api private
|
128
|
-
def collection_class
|
129
|
-
ManyToMany::Collection
|
130
|
-
end
|
131
|
-
end # class Relationship
|
132
|
-
|
133
|
-
class Collection < Associations::OneToMany::Collection
|
134
|
-
remove_method :_save
|
135
|
-
remove_method :_create
|
136
|
-
|
137
|
-
def inverse_add(*resources)
|
138
|
-
resources.each do |r|
|
139
|
-
r.send(relationship.inverse.name)._original_add(source)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
alias :_original_add :"<<"
|
144
|
-
def <<(resource)
|
145
|
-
resource.send(relationship.inverse.name)._original_add(source)
|
146
|
-
_original_add(resource)
|
147
|
-
end
|
148
|
-
|
149
|
-
alias :_original_concat :concat
|
150
|
-
def concat(resources)
|
151
|
-
inverse_add(*resources)
|
152
|
-
_original_concat(resources)
|
153
|
-
end
|
154
|
-
|
155
|
-
alias :_original_push :push
|
156
|
-
def push(*resources)
|
157
|
-
inverse_add(*resources)
|
158
|
-
_original_push(*resources)
|
159
|
-
end
|
160
|
-
|
161
|
-
|
162
|
-
alias :_original_unshift :unshift
|
163
|
-
def unshift(*resources)
|
164
|
-
inverse_add(*resources)
|
165
|
-
_original_unshift(*resources)
|
166
|
-
end
|
167
|
-
|
168
|
-
alias :_original_insert :insert
|
169
|
-
def insert(offset, *resources)
|
170
|
-
inverse_add(*resources)
|
171
|
-
_original_insert(offset, *resources)
|
172
|
-
end
|
173
|
-
|
174
|
-
alias :_original_delete :delete
|
175
|
-
def delete(resource)
|
176
|
-
result = _original_delete(resource)
|
177
|
-
resource.send(relationship.inverse.name)._original_delete(source)
|
178
|
-
result
|
179
|
-
end
|
180
|
-
|
181
|
-
alias :_original_pop :pop
|
182
|
-
def pop(*)
|
183
|
-
removed = _original_pop
|
184
|
-
removed._original_delete(source) unless removed.nil?
|
185
|
-
removed
|
186
|
-
end
|
187
|
-
|
188
|
-
alias :_original_shift :shift
|
189
|
-
def shift(*)
|
190
|
-
removed = _original_pop
|
191
|
-
removed._original_delete(source) unless removed.nil?
|
192
|
-
removed
|
193
|
-
end
|
194
|
-
|
195
|
-
alias :_original_delete_at :delete_at
|
196
|
-
def delete_at(offset)
|
197
|
-
resource = _original_delete_at(offset)
|
198
|
-
resource._original_delete(source) unless removed.nil?
|
199
|
-
resource
|
200
|
-
end
|
201
|
-
|
202
|
-
# alias :_original_delete_if :delete_if
|
203
|
-
def delete_if
|
204
|
-
results = super { |resource| yield(resource) && resource_removed(resource) }
|
205
|
-
results.each{|r| r._original_delete(source) }
|
206
|
-
results
|
207
|
-
end
|
208
|
-
|
209
|
-
def reject!
|
210
|
-
results = super { |resource| yield(resource) && resource_removed(resource) }
|
211
|
-
results.each{|r| r._original_delete(source) }
|
212
|
-
results
|
213
|
-
end
|
214
|
-
|
215
|
-
def replace(other)
|
216
|
-
other = resources_added(other)
|
217
|
-
removed = entries - other
|
218
|
-
new_resources = other - removed
|
219
|
-
resources_removed(removed)
|
220
|
-
removed.each{ |r| delete(r) }
|
221
|
-
new_resources.each do |resource|
|
222
|
-
resource.send(relationship.inverse.name)._original_add(source)
|
223
|
-
_original_add(resource)
|
224
|
-
end
|
225
|
-
super(other)
|
226
|
-
end
|
227
|
-
|
228
|
-
alias :_original_clear :clear
|
229
|
-
def clear
|
230
|
-
self.each{|r| r._original_delete(source) }
|
231
|
-
_original_clear
|
232
|
-
end
|
233
|
-
|
234
|
-
# TODO: Add these
|
235
|
-
# slice!, splice, collect!
|
236
|
-
|
237
|
-
def _save(safe)
|
238
|
-
loaded_entries = self.loaded_entries
|
239
|
-
@removed.clear
|
240
|
-
loaded_entries.all? { |resource| resource.__send__(safe ? :save : :save!) }
|
241
|
-
end
|
242
|
-
|
243
|
-
private
|
244
|
-
|
245
|
-
# Track the added resource
|
246
|
-
#
|
247
|
-
# @param [Resource] resource
|
248
|
-
# the resource that was added
|
249
|
-
#
|
250
|
-
# @return [Resource]
|
251
|
-
# the resource that was added
|
252
|
-
#
|
253
|
-
# @api private
|
254
|
-
def resource_added(resource)
|
255
|
-
resource = initialize_resource(resource)
|
256
|
-
|
257
|
-
if resource.saved?
|
258
|
-
@identity_map[resource.key] = resource
|
259
|
-
@removed.delete(resource)
|
260
|
-
else
|
261
|
-
resource.save
|
262
|
-
end
|
263
|
-
resource
|
264
|
-
end
|
265
|
-
|
266
|
-
# @api private
|
267
|
-
def resource_removed(resource)
|
268
|
-
if resource.saved?
|
269
|
-
@identity_map.delete(resource.key)
|
270
|
-
@removed << resource
|
271
|
-
end
|
272
|
-
|
273
|
-
resource
|
274
|
-
end
|
275
|
-
end # class Collection
|
276
|
-
end # module ManyToMany
|
277
|
-
end # module Associations
|
278
|
-
end # module DataMapper
|
@@ -1,57 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Associations
|
3
|
-
class Relationship
|
4
|
-
|
5
|
-
# Prefix
|
6
|
-
# @example property.prefix
|
7
|
-
# @return [String]
|
8
|
-
# @api public
|
9
|
-
attr_accessor :prefix
|
10
|
-
|
11
|
-
def to_json_schema_hash
|
12
|
-
child = self.child_model
|
13
|
-
parent = self.parent_model
|
14
|
-
relationship_schema = {}
|
15
|
-
|
16
|
-
case self
|
17
|
-
when DataMapper::Associations::ManyToMany::Relationship
|
18
|
-
# puts "-> M:M #{child.storage_name}"
|
19
|
-
relationship_schema = { "type" => "array",
|
20
|
-
"dm_relation" => "many_to_many",
|
21
|
-
"lazy" => true,
|
22
|
-
"optional" => true,
|
23
|
-
"items" => {"$ref" => "/Class/#{child.storage_name}"},
|
24
|
-
"minItems" => self.min
|
25
|
-
}
|
26
|
-
relationship_schema["maxItems"] = self.max if self.max != Infinity
|
27
|
-
when DataMapper::Associations::OneToMany::Relationship
|
28
|
-
# puts "-> 1:M #{child.storage_name}"
|
29
|
-
relationship_schema = { "type" => "array",
|
30
|
-
"dm_relation" => "has_n",
|
31
|
-
"lazy" => true,
|
32
|
-
"optional" => true,
|
33
|
-
"items" => {"$ref" => "/Class/#{child.storage_name}"},
|
34
|
-
"minItems" => self.min
|
35
|
-
}
|
36
|
-
relationship_schema["maxItems"] = self.max if self.max != Infinity
|
37
|
-
when DataMapper::Associations::ManyToOne::Relationship
|
38
|
-
# puts "-> M:1 #{parent.storage_name}"
|
39
|
-
relationship_schema = { "type" => { "$ref" => "/Class/#{parent.storage_name}" },
|
40
|
-
"dm_relation" => "belongs_to",
|
41
|
-
"lazy" => true,
|
42
|
-
"optional" => true }
|
43
|
-
when DataMapper::Associations::OneToOne::Relationship
|
44
|
-
# puts "-> 1:1 #{child.storage_name}"
|
45
|
-
relationship_schema = { "type" => { "$ref" => "/Class/#{child.storage_name}" },
|
46
|
-
"dm_relation" => "has_n",
|
47
|
-
"lazy" => true,
|
48
|
-
"optional" => true }
|
49
|
-
end
|
50
|
-
|
51
|
-
relationship_schema.merge!("prefix" => @prefix ) unless @prefix.nil?
|
52
|
-
return relationship_schema
|
53
|
-
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/dm/model.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Model
|
3
|
-
# module Json
|
4
|
-
def to_json_schema(repository_name = default_repository_name)
|
5
|
-
to_json_schema_hash(repository_name).to_json
|
6
|
-
end
|
7
|
-
|
8
|
-
#TODO: Add various options in.
|
9
|
-
def to_json_schema_hash(repository_name = default_repository_name)
|
10
|
-
schema_hash = {
|
11
|
-
'id' => self.storage_name(repository_name),
|
12
|
-
'prototype' => Hash.new,
|
13
|
-
'properties' => Hash.new
|
14
|
-
}
|
15
|
-
|
16
|
-
# Handle properties
|
17
|
-
properties.select { |prop| prop.field != 'id' }.each do |prop|
|
18
|
-
schema_hash['properties'][prop.field] = prop.to_json_schema_hash(repository_name)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Handle relationships
|
22
|
-
relationships.each_pair do |nom,relation|
|
23
|
-
next if self.name.downcase == nom
|
24
|
-
schema_hash['properties'][nom] = relation.to_json_schema_hash
|
25
|
-
end
|
26
|
-
return schema_hash
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
data/lib/dm/property.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
class Property
|
3
|
-
|
4
|
-
def to_json_schema_hash(repo)
|
5
|
-
|
6
|
-
tm = repository(repo).adapter.type_map
|
7
|
-
type_information = tm[type]
|
8
|
-
if type_information.nil? && type.respond_to?(:primitive)
|
9
|
-
type_information = tm[type.primitive]
|
10
|
-
end
|
11
|
-
|
12
|
-
json_hash = Hash.new
|
13
|
-
json_hash = { "type" => type_information[:primitive] }
|
14
|
-
json_hash.merge!({ "optional" => true }) unless required?
|
15
|
-
json_hash.merge!({ "unique" => true}) if unique?
|
16
|
-
json_hash.merge!({ "position" => @position }) unless @position.nil?
|
17
|
-
json_hash.merge!({ "prefix" => @prefix }) unless @prefix.nil?
|
18
|
-
json_hash.merge!({ "separator" => @separator }) unless @separator.nil?
|
19
|
-
json_hash.merge!( type_information.reject{ |key,value| key == :primitive } )
|
20
|
-
|
21
|
-
json_hash
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
data/lib/dm/query.rb
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
class Query
|
3
|
-
##
|
4
|
-
def munge_condition(condition)
|
5
|
-
loaded_value = condition.loaded_value
|
6
|
-
return_value = ""
|
7
|
-
|
8
|
-
if condition.subject.is_a?(DataMapper::Property)
|
9
|
-
rhs = case loaded_value
|
10
|
-
when String then "\"#{loaded_value}\""
|
11
|
-
when DateTime then "date(%10.f)" % (Time.parse(loaded_value.to_s).to_f * 1000)
|
12
|
-
when nil then "undefined"
|
13
|
-
else loaded_value
|
14
|
-
end
|
15
|
-
return_value = "#{condition.subject.field}#{condition.__send__(:comparator_string)}#{rhs}"
|
16
|
-
end
|
17
|
-
|
18
|
-
return_value = _fugly_munger(condition, loaded_value) if condition.subject.is_a?(DataMapper::Associations::Relationship)
|
19
|
-
return_value
|
20
|
-
end
|
21
|
-
|
22
|
-
def _fugly_munger(condition, loaded_value)
|
23
|
-
subject = condition.subject
|
24
|
-
|
25
|
-
case subject
|
26
|
-
when DataMapper::Associations::ManyToMany::Relationship then
|
27
|
-
return_value = "#{condition.subject.field}.contains(/#{subject.child_model.storage_name}/#{loaded_value.key.first})"
|
28
|
-
when DataMapper::Associations::OneToMany::Relationship then
|
29
|
-
return_value = "#{condition.subject.field}.contains(/#{subject.parent_model.storage_name}/#{loaded_value.key.first})"
|
30
|
-
when DataMapper::Associations::OneToOne::Relationship then
|
31
|
-
if loaded_value.nil?
|
32
|
-
return_value = "#{condition.subject.field}#{condition.__send__(:comparator_string)}undefined"
|
33
|
-
else
|
34
|
-
return_value = "#{condition.subject.field}#{condition.__send__(:comparator_string)}/#{subject.parent_model.storage_name}/#{loaded_value.key.first}"
|
35
|
-
end
|
36
|
-
when DataMapper::Associations::ManyToOne::Relationship then
|
37
|
-
if self.model != subject.child_model
|
38
|
-
return_value = "#{condition.subject.field}.contains(/#{subject.parent_model.storage_name}/#{loaded_value.key.first})"
|
39
|
-
else
|
40
|
-
if loaded_value.nil?
|
41
|
-
return_value = "#{condition.subject.field}#{condition.__send__(:comparator_string)}undefined"
|
42
|
-
else
|
43
|
-
return_value = "#{condition.subject.field}#{condition.__send__(:comparator_string)}/#{subject.parent_model.storage_name}/#{loaded_value.key.first}"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
##
|
50
|
-
def process_condition(condition)
|
51
|
-
case condition
|
52
|
-
# Persevere 1.0 regular expressions are disable for security so we pass them back for DataMapper query filtering
|
53
|
-
# without regular expressions, the like operator is inordinately challenging hence we pass it back
|
54
|
-
# when :regexp then "RegExp(\"#{condition.value.source}\").test(#{condition.subject.name})"
|
55
|
-
when DataMapper::Query::Conditions::RegexpComparison then []
|
56
|
-
when DataMapper::Query::Conditions::LikeComparison then "#{condition.subject.field}='#{condition.loaded_value.gsub('%', '*')}'"
|
57
|
-
when DataMapper::Query::Conditions::AndOperation then
|
58
|
-
inside = condition.operands.map { |op| process_condition(op) }.flatten
|
59
|
-
inside.empty? ? [] : "(#{inside.join("&")})"
|
60
|
-
when DataMapper::Query::Conditions::OrOperation then "(#{condition.operands.map { |op| process_condition(op) }.join("|")})"
|
61
|
-
when DataMapper::Query::Conditions::NotOperation then
|
62
|
-
inside = process_condition(condition.operand)
|
63
|
-
inside.empty? ? [] : "!(%s)" % inside
|
64
|
-
when DataMapper::Query::Conditions::InclusionComparison then
|
65
|
-
result_string = Array.new
|
66
|
-
condition.value.to_a.each do |candidate|
|
67
|
-
if condition.subject.is_a?(DataMapper::Associations::Relationship)
|
68
|
-
result_string << _fugly_munger(condition, candidate)
|
69
|
-
else
|
70
|
-
result_string << "#{condition.subject.name}=#{candidate}"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
if result_string.length > 0
|
74
|
-
"(#{result_string.join("|")})"
|
75
|
-
else
|
76
|
-
"#{condition.subject.name}=''"
|
77
|
-
end
|
78
|
-
when DataMapper::Query::Conditions::EqualToComparison,
|
79
|
-
DataMapper::Query::Conditions::GreaterThanComparison,
|
80
|
-
DataMapper::Query::Conditions::LessThanComparison,
|
81
|
-
DataMapper::Query::Conditions::GreaterThanOrEqualToComparison,
|
82
|
-
DataMapper::Query::Conditions::LessThanOrEqualToComparison then
|
83
|
-
munge_condition(condition)
|
84
|
-
when DataMapper::Query::Conditions::NullOperation then []
|
85
|
-
when Array then
|
86
|
-
old_statement, bind_values = condition
|
87
|
-
statement = old_statement.dup
|
88
|
-
bind_values.each{ |bind_value| statement.sub!('?', bind_value.to_s) }
|
89
|
-
statement.gsub(' ', '')
|
90
|
-
else condition.to_s.gsub(' ', '')
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
##
|
95
|
-
# Convert a DataMapper Query to a JSON Query.
|
96
|
-
#
|
97
|
-
# @param [Query] query
|
98
|
-
# The DataMapper query object passed in
|
99
|
-
#
|
100
|
-
# @api semipublic
|
101
|
-
def to_json_query
|
102
|
-
|
103
|
-
# Body of main function
|
104
|
-
json_query = ""
|
105
|
-
query_terms = Array.new
|
106
|
-
order_operations = Array.new
|
107
|
-
field_ops = Array.new
|
108
|
-
outfields = Array.new
|
109
|
-
headers = Hash.new
|
110
|
-
|
111
|
-
query_terms << process_condition(conditions)
|
112
|
-
|
113
|
-
if query_terms.flatten.length != 0
|
114
|
-
json_query += "[?#{query_terms.join("][?")}]"
|
115
|
-
end
|
116
|
-
|
117
|
-
self.fields.each do |field|
|
118
|
-
if field.respond_to?(:operator)
|
119
|
-
field_ops << case field.operator
|
120
|
-
when :count then
|
121
|
-
if field.target.is_a?(DataMapper::Property)
|
122
|
-
"[?#{field.target.field}!=undefined].length"
|
123
|
-
else # field.target is all.
|
124
|
-
".length"
|
125
|
-
end
|
126
|
-
when :min
|
127
|
-
if field.target.type == DateTime || field.target.type == Time || field.target.type == Date
|
128
|
-
"[=#{field.target.field}]"
|
129
|
-
else
|
130
|
-
".min(?#{field.target.field})"
|
131
|
-
end
|
132
|
-
when :max
|
133
|
-
if field.target.type == DateTime || field.target.type == Time || field.target.type == Date
|
134
|
-
"[=#{field.target.field}]"
|
135
|
-
else
|
136
|
-
".max(?#{field.target.field})"
|
137
|
-
end
|
138
|
-
when :sum
|
139
|
-
".sum(?#{field.target.field})"
|
140
|
-
when :avg
|
141
|
-
"[=#{field.target.field}]"
|
142
|
-
end
|
143
|
-
else
|
144
|
-
outfields << "'#{field.field}':#{field.field}"
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
json_query += field_ops.join("")
|
149
|
-
|
150
|
-
if order && order.any?
|
151
|
-
order.map do |direction|
|
152
|
-
order_operations << case direction.operator
|
153
|
-
when :asc then "[\/#{direction.target.field}]"
|
154
|
-
when :desc then "[\\#{direction.target.field}]"
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
json_query += order_operations.join("")
|
160
|
-
|
161
|
-
json_query += "[={" + outfields.join(',') + "}]" unless outfields.empty?
|
162
|
-
|
163
|
-
offset = self.offset.to_i
|
164
|
-
limit = self.limit.nil? ? nil : self.limit.to_i + offset - 1
|
165
|
-
|
166
|
-
if offset != 0 || !limit.nil?
|
167
|
-
headers.merge!( {"Range" => "items=#{offset}-#{limit}"} )
|
168
|
-
end
|
169
|
-
# puts "#{inspect}"
|
170
|
-
# puts json_query, headers
|
171
|
-
return json_query, headers
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|