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