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
@@ -0,0 +1,75 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Persevere
|
3
|
+
module Aggregates
|
4
|
+
def aggregate(query)
|
5
|
+
records = []
|
6
|
+
fields = query.fields
|
7
|
+
field_size = fields.size
|
8
|
+
|
9
|
+
connect if @persevere.nil?
|
10
|
+
resources = Array.new
|
11
|
+
|
12
|
+
query = Persevere.enhance(query)
|
13
|
+
|
14
|
+
json_query, headers = query.to_json_query
|
15
|
+
path = "/#{query.model.storage_name}/#{json_query}"
|
16
|
+
DataMapper.logger.debug("--> PATH/QUERY/HEADERS: #{path} #{headers.inspect}")
|
17
|
+
|
18
|
+
response = @persevere.retrieve(path, headers)
|
19
|
+
|
20
|
+
if response.code == "200"
|
21
|
+
results = [response.body]
|
22
|
+
results.each do |row_of_results|
|
23
|
+
row = query.fields.zip([row_of_results].flatten).map do |field, value|
|
24
|
+
if field.respond_to?(:operator)
|
25
|
+
send(field.operator, field.target, value)
|
26
|
+
else
|
27
|
+
field.typecast(value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
records << (field_size > 1 ? row : row[0])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
records
|
34
|
+
end # aggregate method
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def count(property, value)
|
39
|
+
value.to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
def min(property, value)
|
43
|
+
values = JSON.parse("[#{value}]").flatten.compact
|
44
|
+
if values.is_a?(Array)
|
45
|
+
values.map! { |v| property.typecast(v) }
|
46
|
+
return values.sort[0].new_offset(Rational(Time.now.getlocal.gmt_offset/3600, 24)) if property.kind_of?(DataMapper::Property::DateTime)
|
47
|
+
return values.sort[0]
|
48
|
+
end
|
49
|
+
property.typecast(value)
|
50
|
+
end
|
51
|
+
|
52
|
+
def max(property, value)
|
53
|
+
values = JSON.parse("[#{value}]").flatten.compact
|
54
|
+
if values.is_a?(Array)
|
55
|
+
values.map! { |v| property.typecast(v) }
|
56
|
+
return values.sort[-1].new_offset(Rational(Time.now.getlocal.gmt_offset/3600, 24)) if property.kind_of?(DataMapper::Property::DateTime)
|
57
|
+
return values.sort[-1]
|
58
|
+
end
|
59
|
+
property.typecast(value)
|
60
|
+
end
|
61
|
+
|
62
|
+
def avg(property, value)
|
63
|
+
values = JSON.parse(value).compact
|
64
|
+
result = values.inject(0.0){|sum,i| sum+=i }/values.length
|
65
|
+
property.kind_of?(DataMapper::Property::Integer) ? result.to_f : property.typecast(result)
|
66
|
+
end
|
67
|
+
|
68
|
+
def sum(property, value)
|
69
|
+
property.typecast(value)
|
70
|
+
end
|
71
|
+
end # module Aggregates
|
72
|
+
end # module Persevere
|
73
|
+
|
74
|
+
DataMapper::Persevere::Adapter.send(:include, DataMapper::Persevere::Aggregates)
|
75
|
+
end # module DataMapper
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Persevere
|
3
|
+
def self.enhance(object)
|
4
|
+
Persevere::Proxy[object]
|
5
|
+
end
|
6
|
+
|
7
|
+
class Proxy
|
8
|
+
instance_methods.each do |m|
|
9
|
+
undef_method(m) if m.to_s !~ /(?:^__|^nil\?$|^send$|^object_id$|^extend$)/
|
10
|
+
end
|
11
|
+
|
12
|
+
def raise(*args)
|
13
|
+
::Object.send(:raise, *args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.[](target)
|
17
|
+
proxy = self.new(target)
|
18
|
+
|
19
|
+
case target
|
20
|
+
when DataMapper::Resource
|
21
|
+
proxy.extend(JSONSupport::Core)
|
22
|
+
proxy.extend(JSONSupport::Resource)
|
23
|
+
when DataMapper::Model
|
24
|
+
proxy.extend(JSONSupport::Core)
|
25
|
+
proxy.extend(JSONSupport::Model)
|
26
|
+
proxy.extend(JSONSupport::Model::Properties)
|
27
|
+
when DataMapper::Property
|
28
|
+
proxy.extend(JSONSupport::Core)
|
29
|
+
proxy.extend(JSONSupport::Property)
|
30
|
+
when DataMapper::Query
|
31
|
+
proxy.extend(Persevere::Query)
|
32
|
+
else
|
33
|
+
return target
|
34
|
+
end
|
35
|
+
return proxy
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(target)
|
39
|
+
|
40
|
+
@target = target
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_missing(method, *args, &block)
|
44
|
+
@target.send(method, *args, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
end # Proxy
|
48
|
+
end # Persevere
|
49
|
+
end # DataMapper
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Persevere
|
3
|
+
module JSONSupport
|
4
|
+
module Core
|
5
|
+
def to_json(id = nil)
|
6
|
+
to_json_hash(id).to_json
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_json_hash(id = nil)
|
10
|
+
return {
|
11
|
+
'id' => id || self.to_s
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end # Core
|
15
|
+
end # JSONSupport
|
16
|
+
end # Persevere
|
17
|
+
end # DataMapper
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Persevere
|
3
|
+
module JSONSupport
|
4
|
+
module Model
|
5
|
+
def to_json_hash(repository_name = default_repository_name)
|
6
|
+
schema_hash = super
|
7
|
+
schema_hash['id'] = self.storage_name(repository_name)
|
8
|
+
schema_hash['prototype'] ||= {}
|
9
|
+
return schema_hash
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_json_schema(repository_name = default_repository_name)
|
13
|
+
to_json(repository_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_json_schema_hash(repository_name = default_repository_name)
|
17
|
+
to_json_hash(repository_name)
|
18
|
+
end
|
19
|
+
end # JSONSchema
|
20
|
+
end # Model
|
21
|
+
end # Persevere
|
22
|
+
end # DataMapper
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Persevere
|
3
|
+
module JSONSupport
|
4
|
+
module Model
|
5
|
+
module Properties
|
6
|
+
#TODO: Add various options in.
|
7
|
+
def to_json_hash(repository_name = default_repository_name)
|
8
|
+
schema_hash = super
|
9
|
+
schema_hash['properties'] ||= {}
|
10
|
+
|
11
|
+
# Handle properties
|
12
|
+
properties.select { |prop| prop.field != 'id' }.each do |prop|
|
13
|
+
prop = Persevere.enhance(prop)
|
14
|
+
schema_hash['properties'][prop.field] = prop.to_json_hash(repository_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
return schema_hash
|
18
|
+
end
|
19
|
+
end # Properties
|
20
|
+
end # Model
|
21
|
+
end # JSON
|
22
|
+
end # Persevere
|
23
|
+
end # DataMapper
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Persevere
|
3
|
+
module JSONSupport
|
4
|
+
module Property
|
5
|
+
def to_json_hash(repo)
|
6
|
+
tm = repository(repo).adapter.type_map
|
7
|
+
type_information = tm[primitive]
|
8
|
+
|
9
|
+
json_hash = Hash.new
|
10
|
+
json_hash = { "type" => type_information[:primitive] }
|
11
|
+
json_hash.merge!({ "optional" => true }) unless required?
|
12
|
+
json_hash.merge!({ "unique" => true}) if unique?
|
13
|
+
json_hash.merge!({ "position" => @position }) unless @position.nil?
|
14
|
+
json_hash.merge!({ "prefix" => @prefix }) unless @prefix.nil?
|
15
|
+
json_hash.merge!({ "separator" => @separator }) unless @separator.nil?
|
16
|
+
json_hash.merge!( type_information.reject{ |key,value| key == :primitive } )
|
17
|
+
|
18
|
+
json_hash
|
19
|
+
end
|
20
|
+
end # Property
|
21
|
+
end # JSON
|
22
|
+
end # Persevere
|
23
|
+
end # DataMapper
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Persevere
|
3
|
+
module JSONSupport
|
4
|
+
module Resource
|
5
|
+
|
6
|
+
##
|
7
|
+
# Convert a DataMapper Resource to a JSON.
|
8
|
+
#
|
9
|
+
# @param [Query] query
|
10
|
+
# The DataMapper query object passed in
|
11
|
+
#
|
12
|
+
# @api semipublic
|
13
|
+
def to_json_hash
|
14
|
+
json_rsrc = Hash.new
|
15
|
+
|
16
|
+
|
17
|
+
attributes(:property).each do |property, value|
|
18
|
+
next if value.nil? #|| (value.is_a?(Array) && value.empty?) || relations.include?(property.name.to_s)
|
19
|
+
|
20
|
+
json_rsrc[property.field] = case value
|
21
|
+
when DateTime then value.new_offset(0).strftime("%Y-%m-%dT%H:%M:%SZ")
|
22
|
+
when Date then value.to_s
|
23
|
+
when Time then value.strftime("%H:%M:%S")
|
24
|
+
when Float then value.to_f
|
25
|
+
when BigDecimal then value.to_f
|
26
|
+
when Integer then value.to_i
|
27
|
+
else # when String, TrueClass, FalseClass then
|
28
|
+
self[property.name]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
json_rsrc
|
33
|
+
end
|
34
|
+
end # Resource
|
35
|
+
end # JSON
|
36
|
+
end # Persevere
|
37
|
+
end # DataMapper
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Persevere
|
3
|
+
module Migrations
|
4
|
+
|
5
|
+
# Returns whether the storage_name exists.
|
6
|
+
#
|
7
|
+
# @param [String] storage_name
|
8
|
+
# a String defining the name of a storage, for example a table name.
|
9
|
+
#
|
10
|
+
# @return [Boolean]
|
11
|
+
# true if the storage exists
|
12
|
+
#
|
13
|
+
# @api semipublic
|
14
|
+
def storage_exists?(storage_name)
|
15
|
+
class_names = JSON.parse(@persevere.retrieve('/Class/[=id]').body)
|
16
|
+
return true if class_names.include?("Class/"+storage_name)
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Creates the persevere schema from the model.
|
22
|
+
#
|
23
|
+
# @param [DataMapper::Model] model
|
24
|
+
# The model that corresponds to the storage schema that needs to be created.
|
25
|
+
#
|
26
|
+
# @api semipublic
|
27
|
+
def create_model_storage(model)
|
28
|
+
model = Persevere.enhance(model)
|
29
|
+
name = self.name
|
30
|
+
properties = model.properties_with_subclasses(name)
|
31
|
+
|
32
|
+
return false if storage_exists?(model.storage_name(name))
|
33
|
+
return false if properties.empty?
|
34
|
+
|
35
|
+
# Make sure storage for referenced objects exists
|
36
|
+
model.relationships.each_pair do |n, r|
|
37
|
+
if ! storage_exists?(r.child_model.storage_name)
|
38
|
+
put_schema({'id' => r.child_model.storage_name, 'properties' => {}})
|
39
|
+
end
|
40
|
+
end
|
41
|
+
schema_hash = model.to_json_schema_hash()
|
42
|
+
|
43
|
+
return true unless put_schema(schema_hash) == false
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Updates the persevere schema from the model.
|
49
|
+
#
|
50
|
+
# @param [DataMapper::Model] model
|
51
|
+
# The model that corresponds to the storage schema that needs to be updated.
|
52
|
+
#
|
53
|
+
# @api semipublic
|
54
|
+
def upgrade_model_storage(model)
|
55
|
+
model = Persevere.enhance(model)
|
56
|
+
name = self.name
|
57
|
+
properties = model.properties_with_subclasses(name)
|
58
|
+
|
59
|
+
DataMapper.logger.debug("Upgrading #{model.name}")
|
60
|
+
|
61
|
+
if success = create_model_storage(model)
|
62
|
+
return properties
|
63
|
+
end
|
64
|
+
|
65
|
+
new_schema_hash = model.to_json_schema_hash()
|
66
|
+
current_schema_hash = get_schema(new_schema_hash['id'])[0]
|
67
|
+
# TODO: Diff of what is there and what will be added.
|
68
|
+
|
69
|
+
new_properties = properties.map do |property|
|
70
|
+
prop_name = property.name.to_s
|
71
|
+
prop_type = property.type
|
72
|
+
next if prop_name == 'id' ||
|
73
|
+
(current_schema_hash['properties'].has_key?(prop_name) &&
|
74
|
+
new_schema_hash['properties'][prop_name]['type'] == current_schema_hash['properties'][prop_name]['type'] )
|
75
|
+
property
|
76
|
+
end.compact
|
77
|
+
|
78
|
+
return new_properties unless update_schema(new_schema_hash) == false
|
79
|
+
return nil
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Destroys the persevere schema from the model.
|
84
|
+
#
|
85
|
+
# @param [DataMapper::Model] model
|
86
|
+
# The model that corresponds to the storage schema that needs to be destroyed.
|
87
|
+
#
|
88
|
+
# @api semipublic
|
89
|
+
def destroy_model_storage(model)
|
90
|
+
model = Persevere.enhance(model)
|
91
|
+
return true unless storage_exists?(model.storage_name(name))
|
92
|
+
schema_hash = model.to_json_schema_hash()
|
93
|
+
return true unless delete_schema(schema_hash) == false
|
94
|
+
false
|
95
|
+
end
|
96
|
+
|
97
|
+
end # module Migrations
|
98
|
+
end # module Persevere
|
99
|
+
end # module DataMapper
|
100
|
+
|
101
|
+
DataMapper::Migrations.include_migration_api
|
102
|
+
DataMapper::Persevere::Adapter.send(:include, DataMapper::Persevere::Migrations)
|
103
|
+
|
104
|
+
|
@@ -0,0 +1,208 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Persevere
|
3
|
+
module Query
|
4
|
+
##
|
5
|
+
# TODO: Clean this mess up.
|
6
|
+
#
|
7
|
+
# @author lamb
|
8
|
+
def munge_condition(condition)
|
9
|
+
loaded_value = condition.loaded_value
|
10
|
+
return_value = ""
|
11
|
+
subject = condition.subject
|
12
|
+
|
13
|
+
if subject.is_a?(DataMapper::Property)
|
14
|
+
rhs = case loaded_value
|
15
|
+
when String then "\"#{loaded_value}\""
|
16
|
+
when DateTime then "date(%10.f)" % (Time.parse(loaded_value.to_s).to_f * 1000)
|
17
|
+
when nil then "undefined"
|
18
|
+
else loaded_value
|
19
|
+
end
|
20
|
+
return_value = "#{condition.subject.field}#{condition.__send__(:comparator_string)}#{rhs}"
|
21
|
+
elsif subject.is_a?(DataMapper::Associations::ManyToOne::Relationship)
|
22
|
+
# Join relationship, bury it down!
|
23
|
+
if self.model != subject.child_model
|
24
|
+
my_side_of_join = links.select{|relation|
|
25
|
+
relation.kind_of?(DataMapper::Associations::ManyToOne::Relationship) &&
|
26
|
+
relation.child_model == subject.child_model &&
|
27
|
+
# I would really like this to not look at the name,
|
28
|
+
# but sometimes they are different object of the same model
|
29
|
+
relation.parent_model.name == self.model.name }.first
|
30
|
+
|
31
|
+
# join_results = subject.child_model.all(subject.field.to_sym => loaded_value)
|
32
|
+
join_results = subject.child_model.all(subject.child_key.first.name => loaded_value[subject.parent_key.first.name])
|
33
|
+
|
34
|
+
return_value = join_results.map{|r| "#{self.model.key.first.name}=#{r[my_side_of_join.child_key.first.name]}"}.join('|')
|
35
|
+
else
|
36
|
+
comparator = loaded_value.nil? ? 'undefined' : loaded_value.key.first
|
37
|
+
return_value = "#{subject.child_key.first.name}#{condition.__send__(:comparator_string)}#{comparator}"
|
38
|
+
end
|
39
|
+
elsif subject.is_a?(DataMapper::Associations::Relationship)
|
40
|
+
if self.model != subject.child_model
|
41
|
+
return_value = "#{subject.child_key.first.name}#{condition.__send__(:comparator_string)}#{loaded_value.key.first}"
|
42
|
+
else
|
43
|
+
comparator = loaded_value.nil? ? 'undefined' : loaded_value.key.first
|
44
|
+
return_value = "#{subject.field}_id#{condition.__send__(:comparator_string)}#{comparator}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
return_value
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
def process_condition(condition)
|
52
|
+
case condition
|
53
|
+
# Persevere 1.0 regular expressions are disable for security so we pass them back for DataMapper query filtering
|
54
|
+
# without regular expressions, the like operator is inordinately challenging hence we pass it back
|
55
|
+
# when :regexp then "RegExp(\"#{condition.value.source}\").test(#{condition.subject.name})"
|
56
|
+
when DataMapper::Query::Conditions::RegexpComparison then []
|
57
|
+
when DataMapper::Query::Conditions::LikeComparison then "#{condition.subject.field}='#{condition.loaded_value.gsub('%', '*')}'"
|
58
|
+
when DataMapper::Query::Conditions::AndOperation then
|
59
|
+
inside = condition.operands.map { |op| process_condition(op) }.flatten
|
60
|
+
inside.empty? ? [] : "(#{inside.join("&")})"
|
61
|
+
when DataMapper::Query::Conditions::OrOperation then "(#{condition.operands.map { |op| process_condition(op) }.join("|")})"
|
62
|
+
when DataMapper::Query::Conditions::NotOperation then
|
63
|
+
inside = process_condition(condition.operand)
|
64
|
+
inside.empty? ? [] : "!(%s)" % inside
|
65
|
+
when DataMapper::Query::Conditions::InclusionComparison then
|
66
|
+
result_string = Array.new
|
67
|
+
condition.value.to_a.each do |candidate|
|
68
|
+
if condition.subject.is_a?(DataMapper::Associations::Relationship)
|
69
|
+
result_string << "#{condition.subject.child_key.first.name}=#{candidate.key.first}" #munge_condition(condition)
|
70
|
+
else
|
71
|
+
result_string << "#{condition.subject.name}=#{candidate}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
if result_string.length > 0
|
75
|
+
"(#{result_string.join("|")})"
|
76
|
+
else
|
77
|
+
"#{condition.subject.name}=''"
|
78
|
+
end
|
79
|
+
when DataMapper::Query::Conditions::EqualToComparison,
|
80
|
+
DataMapper::Query::Conditions::GreaterThanComparison,
|
81
|
+
DataMapper::Query::Conditions::LessThanComparison,
|
82
|
+
DataMapper::Query::Conditions::GreaterThanOrEqualToComparison,
|
83
|
+
DataMapper::Query::Conditions::LessThanOrEqualToComparison then
|
84
|
+
munge_condition(condition)
|
85
|
+
when DataMapper::Query::Conditions::NullOperation then []
|
86
|
+
when Array then
|
87
|
+
old_statement, bind_values = condition
|
88
|
+
statement = old_statement.dup
|
89
|
+
bind_values.each{ |bind_value| statement.sub!('?', bind_value.to_s) }
|
90
|
+
statement.gsub(' ', '')
|
91
|
+
else condition.to_s.gsub(' ', '')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Convert a DataMapper Query to a JSON Query.
|
97
|
+
#
|
98
|
+
# @param [Query] query
|
99
|
+
# The DataMapper query object passed in
|
100
|
+
#
|
101
|
+
# @api semipublic
|
102
|
+
def to_json_query
|
103
|
+
# Body of main function
|
104
|
+
|
105
|
+
json_query = ''
|
106
|
+
field_ops = Array.new
|
107
|
+
outfields = Array.new
|
108
|
+
|
109
|
+
json_query += self.to_json_query_filter
|
110
|
+
|
111
|
+
self.fields.each do |field|
|
112
|
+
if field.respond_to?(:operator)
|
113
|
+
field_ops << case field.operator
|
114
|
+
when :count then
|
115
|
+
if field.target.is_a?(DataMapper::Property)
|
116
|
+
"[?#{field.target.field}!=undefined].length"
|
117
|
+
else # field.target is all.
|
118
|
+
".length"
|
119
|
+
end
|
120
|
+
when :min
|
121
|
+
if field.target.kind_of?(DataMapper::Property::DateTime) ||
|
122
|
+
field.target.kind_of?(DataMapper::Property::Time) ||
|
123
|
+
field.target.kind_of?(DataMapper::Property::Date)
|
124
|
+
"[=#{field.target.field}]"
|
125
|
+
else
|
126
|
+
".min(?#{field.target.field})"
|
127
|
+
end
|
128
|
+
when :max
|
129
|
+
if field.target.kind_of?(DataMapper::Property::DateTime) ||
|
130
|
+
field.target.kind_of?(DataMapper::Property::Time) ||
|
131
|
+
field.target.kind_of?(DataMapper::Property::Date)
|
132
|
+
"[=#{field.target.field}]"
|
133
|
+
else
|
134
|
+
".max(?#{field.target.field})"
|
135
|
+
end
|
136
|
+
when :sum
|
137
|
+
".sum(?#{field.target.field})"
|
138
|
+
when :avg
|
139
|
+
"[=#{field.target.field}]"
|
140
|
+
end
|
141
|
+
else
|
142
|
+
outfields << "'#{field.field}':#{field.field}"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
json_query += field_ops.join("")
|
147
|
+
|
148
|
+
json_query += self.to_json_query_ordering
|
149
|
+
|
150
|
+
json_query += "[={" + outfields.join(',') + "}]" unless outfields.empty?
|
151
|
+
|
152
|
+
|
153
|
+
# puts json_query, headers
|
154
|
+
return json_query, self.json_query_headers
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# The filter portion on a json query
|
159
|
+
#
|
160
|
+
# @author lamb
|
161
|
+
def to_json_query_filter
|
162
|
+
query_terms = []
|
163
|
+
query_terms << process_condition(conditions)
|
164
|
+
|
165
|
+
if query_terms.flatten.length != 0
|
166
|
+
return "[?#{query_terms.join("][?")}]"
|
167
|
+
else
|
168
|
+
return ''
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
##
|
174
|
+
# The ordering portion of a json query
|
175
|
+
#
|
176
|
+
# @author lamb
|
177
|
+
def to_json_query_ordering
|
178
|
+
order_operations = []
|
179
|
+
if order && order.any?
|
180
|
+
order.map do |direction|
|
181
|
+
order_operations << case direction.operator
|
182
|
+
when :asc then "[\/#{direction.target.field}]"
|
183
|
+
when :desc then "[\\#{direction.target.field}]"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
order_operations.join("")
|
189
|
+
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# The headers of a json query
|
193
|
+
#
|
194
|
+
# @author lamb
|
195
|
+
def json_query_headers
|
196
|
+
headers = Hash.new
|
197
|
+
offset = self.offset.to_i
|
198
|
+
limit = self.limit.nil? ? nil : self.limit.to_i + offset - 1
|
199
|
+
|
200
|
+
if offset != 0 || !limit.nil?
|
201
|
+
headers.merge!( {"Range" => "items=#{offset}-#{limit}"} )
|
202
|
+
end
|
203
|
+
return headers
|
204
|
+
end
|
205
|
+
|
206
|
+
end # Query
|
207
|
+
end # Persevere
|
208
|
+
end # DataMapper
|