datamapper4rails 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +37 -0
  3. data/README.txt +151 -0
  4. data/Rakefile +48 -0
  5. data/datamapper_rails_templates.rb +114 -0
  6. data/generators/datamapper_install/datamapper_install_generator.rb +12 -0
  7. data/generators/datamapper_install/templates/datamapper.rake +88 -0
  8. data/generators/datamapper_model/datamapper_model_generator.rb +18 -0
  9. data/generators/datamapper_model/templates/migration.rb +18 -0
  10. data/generators/datamapper_model/templates/model.rb +14 -0
  11. data/generators/datamapper_rspec_model/datamapper_rspec_model_generator.rb +18 -0
  12. data/generators/datamapper_rspec_model/templates/model_spec.rb +44 -0
  13. data/generators/datamapper_rspec_scaffold/datamapper_rspec_scaffold_generator.rb +20 -0
  14. data/generators/datamapper_rspec_scaffold/templates/controller_spec.rb +171 -0
  15. data/generators/datamapper_rspec_scaffold/templates/edit_erb_spec.rb +25 -0
  16. data/generators/datamapper_scaffold/datamapper_scaffold_generator.rb +31 -0
  17. data/generators/datamapper_scaffold/templates/controller.rb +90 -0
  18. data/generators/datamapper_scaffold/templates/functional_test.rb +49 -0
  19. data/generators/datamapper_scaffold/templates/view_edit.html.erb +18 -0
  20. data/generators/datamapper_scaffold/templates/view_index.html.erb +24 -0
  21. data/generators/datamapper_scaffold/templates/view_new.html.erb +17 -0
  22. data/generators/datamapper_scaffold/templates/view_show.html.erb +10 -0
  23. data/lib/datamapper4rails.rb +14 -0
  24. data/lib/datamapper4rails/adapters/base_adapter.rb +198 -0
  25. data/lib/datamapper4rails/adapters/restful_adapter.rb +320 -0
  26. data/lib/datamapper4rails/datamapper_store.rb +28 -0
  27. data/lib/datamapper4rails/identity_maps.rb +25 -0
  28. data/lib/datamapper4rails/integration_test.rb +45 -0
  29. data/lib/datamapper4rails/overlay.rb +69 -0
  30. data/lib/datamapper4rails/preload_models.rb +26 -0
  31. data/lib/datamapper4rails/restful_transactions.rb +43 -0
  32. data/lib/datamapper4rails/rspec.rb +8 -0
  33. data/lib/datamapper4rails/rspec_default_values.rb +23 -0
  34. data/lib/datamapper4rails/version.rb +3 -0
  35. data/spec/datamapper_store_spec.rb +23 -0
  36. data/spec/spec.opts +1 -0
  37. data/spec/spec_helper.rb +34 -0
  38. metadata +124 -0
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ class <%= controller_class_name %>ControllerTest < ActionController::TestCase
4
+ test "should get index" do
5
+ get :index
6
+ assert_response :success
7
+ assert_not_nil assigns(:<%= table_name %>)
8
+ end
9
+
10
+ test "should get new" do
11
+ get :new
12
+ assert_response :success
13
+ end
14
+
15
+ test "should create <%= file_name %>" do
16
+ assert_difference('<%= class_name %>.all.size') do
17
+ post :create, :<%= file_name %> => {
18
+ <% attributes.each_with_index do |attribute, attribute_index| -%>
19
+ :<%= attribute.name %> => <%= attribute.default_value %><%= attribute_index == attributes.length - 1 ? '' : ','%>
20
+ <% end -%>
21
+ }
22
+ end
23
+
24
+ assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>).key)
25
+ end
26
+
27
+ test "should show <%= file_name %>" do
28
+ get :show, :id => <%= table_name %>(:one).to_param
29
+ assert_response :success
30
+ end
31
+
32
+ test "should get edit" do
33
+ get :edit, :id => <%= table_name %>(:one).to_param
34
+ assert_response :success
35
+ end
36
+
37
+ test "should update <%= file_name %>" do
38
+ put :update, :id => <%= table_name %>(:one).to_param, :<%= file_name %> => { }
39
+ assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>).key)
40
+ end
41
+
42
+ test "should destroy <%= file_name %>" do
43
+ assert_difference('<%= class_name %>.all.size', -1) do
44
+ delete :destroy, :id => <%= table_name %>(:one).to_param
45
+ end
46
+
47
+ assert_redirected_to <%= table_name %>_path
48
+ end
49
+ end
@@ -0,0 +1,18 @@
1
+ <h1>Editing <%= singular_name %></h1>
2
+
3
+ <%% form_for(:<%= singular_name %>, :url => <%= singular_name %>_path(@<%= singular_name %>.key), :html => {:method => :put}) do |f| %>
4
+ <%%= f.error_messages %>
5
+
6
+ <% for attribute in attributes -%>
7
+ <p>
8
+ <%%= f.label :<%= attribute.name %> %><br />
9
+ <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
10
+ </p>
11
+ <% end -%>
12
+ <p>
13
+ <%%= f.submit 'Update' %>
14
+ </p>
15
+ <%% end %>
16
+
17
+ <%%= link_to 'Show', <%= singular_name %>_path(@<%= singular_name %>.key) %> |
18
+ <%%= link_to 'Back', <%= plural_name %>_path %>
@@ -0,0 +1,24 @@
1
+ <h1>Listing <%= plural_name %></h1>
2
+
3
+ <table>
4
+ <tr>
5
+ <% for attribute in attributes -%>
6
+ <th><%= attribute.column.human_name %></th>
7
+ <% end -%>
8
+ </tr>
9
+
10
+ <%% @<%= plural_name %>.each do |<%= singular_name %>| %>
11
+ <tr>
12
+ <% for attribute in attributes -%>
13
+ <td><%%=h <%= singular_name %>.<%= attribute.name %> %></td>
14
+ <% end -%>
15
+ <td><%%= link_to 'Show', <%= singular_name %>_path(<%= singular_name %>.key) %></td>
16
+ <td><%%= link_to 'Edit', edit_<%= singular_name %>_path(<%= singular_name %>.key) %></td>
17
+ <td><%%= link_to 'Destroy', <%= singular_name %>_path(<%= singular_name %>.key), :confirm => 'Are you sure?', :method => :delete %></td>
18
+ </tr>
19
+ <%% end %>
20
+ </table>
21
+
22
+ <br />
23
+
24
+ <%%= link_to 'New <%= singular_name %>', new_<%= singular_name %>_path %>
@@ -0,0 +1,17 @@
1
+ <h1>New <%= singular_name %></h1>
2
+
3
+ <%% form_for(@<%= singular_name %>) do |f| %>
4
+ <%%= f.error_messages %>
5
+
6
+ <% for attribute in attributes -%>
7
+ <p>
8
+ <%%= f.label :<%= attribute.name %> %><br />
9
+ <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
10
+ </p>
11
+ <% end -%>
12
+ <p>
13
+ <%%= f.submit 'Create' %>
14
+ </p>
15
+ <%% end %>
16
+
17
+ <%%= link_to 'Back', <%= plural_name %>_path %>
@@ -0,0 +1,10 @@
1
+ <% for attribute in attributes -%>
2
+ <p>
3
+ <b><%= attribute.column.human_name %>:</b>
4
+ <%%=h @<%= singular_name %>.<%= attribute.name %> %>
5
+ </p>
6
+
7
+ <% end -%>
8
+
9
+ <%%= link_to 'Edit', edit_<%= singular_name %>_path(@<%= singular_name %>.key) %> |
10
+ <%%= link_to 'Back', <%= plural_name %>_path %>
@@ -0,0 +1,14 @@
1
+ require 'rails_datamapper'
2
+ require 'rack-datamapper'
3
+ require 'datamapper4rails/datamapper_store'
4
+
5
+ # keep this here until rails_datamapper has it included
6
+ module DataMapper
7
+ module Validate
8
+ class ValidationErrors
9
+ def count
10
+ size
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,198 @@
1
+ require 'dm-core'
2
+ require 'slf4r'
3
+
4
+ module DataMapper
5
+ module Adapters
6
+ class NoopTransaction
7
+
8
+ def close ; end
9
+ def begin ; end
10
+ def prepare ; end
11
+ def commit ; end
12
+ def rollback ; end
13
+ def rollback_prepared ; end
14
+
15
+ end
16
+ class BaseAdapter < AbstractAdapter
17
+
18
+ include Slf4r::Logger
19
+
20
+ # @see AbstractAdapter
21
+ def transaction_primitive
22
+ NoopTransaction.new
23
+ end
24
+
25
+ def initialize(name, uri_or_options)
26
+ super(name, uri_or_options)
27
+ end
28
+
29
+ protected
30
+
31
+ # checks whether a given resource fullfils the conditions
32
+ # @param [DataMapper::Resource] resource
33
+ # @param [Array<Condition>] conditions
34
+ # @return [Boolean]
35
+ # true if the resource are within the conditions otherwise false
36
+ def filter_resource(resource, conditions)
37
+ #puts "condi"
38
+ #p conditions
39
+ # no conditation => no filter
40
+ if conditions.size == 0
41
+ true
42
+ else
43
+ conditions.all? do |tuple|
44
+ operator, property, bind_value = *tuple
45
+
46
+ value = property.get!(resource)
47
+ case operator
48
+ when :eql, :in then equality_comparison(bind_value, value)
49
+ when :not then !equality_comparison(bind_value, value)
50
+ when :like then Regexp.new(bind_value.gsub(/%/, ".*")) =~ value
51
+ when :gt then !value.nil? && value > bind_value
52
+ when :gte then !value.nil? && value >= bind_value
53
+ when :lt then !value.nil? && value < bind_value
54
+ when :lte then !value.nil? && value <= bind_value
55
+ else raise "Invalid query operator: #{operator.inspect}"
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ # helper method to dispatch the equality test for different
62
+ # classes
63
+ def equality_comparison(bind_value, value)
64
+ case bind_value
65
+ when Array, Range then bind_value.include?(value)
66
+ when NilClass then value.nil?
67
+ else bind_value == value
68
+ end
69
+ end
70
+
71
+ public
72
+
73
+ # @see AbstractAdapter
74
+ # @param [Array<DataMapper::Resources>] resources
75
+ # aaaa
76
+ # @return [Fixnum]
77
+ # number of the newly created resources
78
+ def create(resources)
79
+ resources.select do |resource|
80
+
81
+ create_resource(resource)
82
+
83
+ end.size # just return the number of create resources
84
+ end
85
+
86
+ # @see AbstractAdapter
87
+ # @param [Hash] attributes
88
+ # collection of attribute, i.e. the name/value pairs which
89
+ # needs to be updated
90
+ # @param [Query]
91
+ # on all resources which are selected by that query the
92
+ # update will be applied
93
+ # @return [Fixnum]
94
+ # number of the updated resources
95
+ def update(attributes, query)
96
+ read_many(query).select do |resource|
97
+
98
+ update_resource(resource, attributes)
99
+
100
+ end.size
101
+ end
102
+
103
+ # @see AbstractAdapter
104
+ # @param [DataMapper::Query] query
105
+ # which selects the resource
106
+ # @return [DataMapper::Resource]
107
+ # the found Resource or nil
108
+ def read_one(query)
109
+ result = read_resource(query)
110
+ if result.is_a? Resource
111
+ result
112
+ elsif result # assume result to be Array with the values
113
+ #puts "------------------"
114
+ #p result
115
+ query.model.load(result, query)
116
+ end
117
+ end
118
+
119
+ # @see AbstractAdapter
120
+ # @param [DataMapper::Query] query
121
+ # which selects the resources
122
+ # @return [DataMapper::Collection]
123
+ # collection of Resources
124
+ def read_many(query)
125
+ Collection.new(query) do |set|
126
+ result = read_resources(query)
127
+ #puts "read_many"
128
+ #p result
129
+ if result.size > 0 and result.first.is_a? Resource
130
+ set.replace(result)
131
+ else
132
+ result.each do |values|
133
+ set.load(values)
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ # @see AbstractAdapter
140
+ # @param [Query] query
141
+ # which selects the resources to be deleted
142
+ # @return [Fixnum]
143
+ # number of the deleted resources
144
+ def delete(query)
145
+ read_many(query).each do |resource|
146
+
147
+ delete_resource(resource)
148
+
149
+ end.size
150
+ end
151
+
152
+ private
153
+
154
+ # @param [DataMapper::Resource] resource
155
+ # which will be created
156
+ # @return [DataMapper::Resource]
157
+ # either the resource itself if the creation was successful or nil
158
+ def create_resource(resource)
159
+ raise NotImplementedError.new
160
+ end
161
+
162
+ # @param [DataMapper::Query] query
163
+ # which selects the resource
164
+ # @return [DataMapper::Resource,Array<String>]
165
+ # the resource or a set of values ordered in the same manner as query.fields attributes
166
+ def read_resource(query)
167
+ raise NotImplementedError.new
168
+ end
169
+
170
+ # @param [DataMapper::Query] query
171
+ # which selects the resources
172
+ # @return [Array<DataMapper::Resource>,Array<String>]
173
+ # resources or ordered values
174
+ # @see #read_resource
175
+ def read_resources(query)
176
+ raise NotImplementedError.new
177
+ end
178
+
179
+ # @param [DataMapper::Resource] resource
180
+ # which will be updated with the given attributes.
181
+ # @param [Hash] attributes
182
+ # the keys are the property names and the values are the new values of that property.
183
+ # @return [DataMapper::Resource]
184
+ # resource on success otherwise nil
185
+ def update_resource(resource, attributes)
186
+ raise NotImplementedError.new
187
+ end
188
+
189
+ # @param [DataMapper::Resource] resource
190
+ # which will be deleted
191
+ # @return [DataMapper::Resource]
192
+ # either the resource if the deletion was successful or nil
193
+ def delete_resource(resource)
194
+ raise NotImplementedError.new
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,320 @@
1
+ require 'datamapper4rails/adapters/base_adapter'
2
+ require 'net/http'
3
+ require 'extlib/inflection'
4
+ require 'extlib/module'
5
+ require 'dm-serializer'
6
+
7
+ module DataMapper
8
+ module Adapters
9
+ class RestfulAdapter < BaseAdapter
10
+
11
+ include ::Slf4r::Logger
12
+
13
+ def resource_name_from_model(model)
14
+ ::Extlib::Inflection.underscore(model.name)
15
+ end
16
+
17
+ def resource_name_from_query(query)
18
+ resource_name_from_model(query.model)
19
+ end
20
+
21
+ def keys_from_query(query)
22
+ keys = query.model.key
23
+ # work around strange missing of properties in model
24
+ # but the query has still the fields :P
25
+ if keys.size == 0
26
+ query.fields.select do |f|
27
+ f.key?
28
+ end
29
+ else
30
+ keys
31
+ end
32
+ end
33
+
34
+ def key_value_from_query(query)
35
+ keys = keys_from_query(query)
36
+ logger.debug { "keys=#{keys.inspect}" }
37
+ if keys.size == 1
38
+ key = keys[0]
39
+ # return the third element of the condition array
40
+ # which belongs to the key
41
+ query.conditions.detect do |c|
42
+ c[1] == key
43
+ end[2]
44
+ else
45
+ raise "compound keys are not supported"
46
+ end
47
+ end
48
+
49
+ def single_entity_query?(query)
50
+ query.conditions.count {|c| c[1].key? and c[0] == :eql} == query.model.key.size
51
+ end
52
+
53
+ def attributes_to_xml(name, attributes)
54
+ xml = "<#{name}>"
55
+ attributes.each do |attr, val|
56
+ xml += "<#{attr.name}>#{val}</#{attr.name}>"
57
+ end
58
+ xml += "</#{name}>"
59
+ end
60
+
61
+ def http_get(uri)
62
+ send_request do |http|
63
+ request = Net::HTTP::Get.new(uri)
64
+ request.basic_auth(@uri[:login],
65
+ @uri[:password]) unless @uri[:login].blank?
66
+ http.request(request)
67
+ end
68
+ end
69
+
70
+ def http_post(uri, data = nil)
71
+ send_request do |http|
72
+ request = Net::HTTP::Post.new(uri, {
73
+ 'content-type' => 'application/xml',
74
+ 'content-length' => data.length.to_s
75
+ })
76
+ request.basic_auth(@uri[:login],
77
+ @uri[:password]) unless @uri[:login].blank?
78
+ http.request(request, data)
79
+ end
80
+ end
81
+
82
+ def http_put(uri, data = nil)
83
+ send_request do |http|
84
+ request = Net::HTTP::Put.new(uri, {
85
+ 'content-type' => 'application/xml',
86
+ 'content-length' => data.length.to_s
87
+ })
88
+ request.basic_auth(@uri[:login],
89
+ @uri[:password]) unless @uri[:login].blank?
90
+ # request.set_form_data(data)
91
+ http.request(request, data)
92
+ end
93
+ end
94
+
95
+ def http_delete(uri)
96
+ send_request do |http|
97
+ request = Net::HTTP::Delete.new(uri)
98
+ request.basic_auth(@uri[:login],
99
+ @uri[:password]) unless @uri[:login].blank?
100
+ http.request(request)
101
+ end
102
+ end
103
+
104
+ def send_request(&block)
105
+ res = nil
106
+ Net::HTTP.start(@uri[:host], @uri[:port].to_i) do |http|
107
+ res = yield(http)
108
+ end
109
+ logger.debug { "response=" + res.code }
110
+ res
111
+ end
112
+
113
+ def parse_resource(xml, model, query = nil)
114
+ elements = {}
115
+ associations = {}
116
+ many_to_many = {}
117
+ xml.elements.collect do |element|
118
+ if element.text.nil?
119
+ if element.attributes['type'] == 'array'
120
+ many_to_many[element.name.gsub('-','_').to_sym] = element
121
+ else
122
+ associations[element.name.gsub('-','_').to_sym] = element
123
+ end
124
+ else
125
+ elements[element.name.gsub('-','_').to_sym] = element.text
126
+ end
127
+ end
128
+ #puts
129
+ #puts "elements"
130
+ #p elements
131
+ #p query
132
+ #p model.properties
133
+ props = model.properties.length == 0 ? query.fields : model.properties
134
+ #p props
135
+ resource = model.load(props.collect do |f| #model.properties.collect do |f|
136
+ elements[f.name]
137
+ end, query)
138
+ #p resource
139
+ #p query
140
+ resource.send("#{keys_from_query(query)[0].name}=".to_sym, elements[keys_from_query(query)[0].name] )
141
+ #p resource
142
+ #p associations
143
+ associations.each do |name, association|
144
+ # puts "asso"
145
+ # p model
146
+ # p name
147
+ # p association
148
+ #p model.relationships
149
+ is_one_to_one = false
150
+ asso_model =
151
+ if rel = model.relationships[name]
152
+ #puts "rel"
153
+ #p rel
154
+ if rel.child_model == model
155
+ rel.parent_model
156
+ else
157
+ rel.child_model
158
+ end
159
+ # else
160
+ #::Extlib::Inflection.constantize(::Extlib::Inflection.classify(name))
161
+ # model.find_const(::Extlib::Inflection.classify(name))
162
+ end
163
+ # p asso_model
164
+ if resource.respond_to? "#{name}=".to_sym
165
+ # puts
166
+ # puts "association"
167
+ # puts name
168
+ # p model
169
+ # p asso_model
170
+ resource.send("#{name}=".to_sym,
171
+ parse_resource(association, asso_model,
172
+ ::DataMapper::Query.new(query.repository, asso_model ))) unless asso_model.nil?
173
+ else
174
+ resource.send("#{name.to_s.pluralize}".to_sym).send(:<<,
175
+ parse_resource(association, asso_model,
176
+ ::DataMapper::Query.new(query.repository, asso_model ))) unless asso_model.nil?
177
+ end
178
+ end
179
+
180
+ #puts "many 2 many"
181
+ #p many_to_many
182
+ many_to_many.each do |name, many|
183
+ if model.relationships[name]
184
+ # TODO
185
+ puts "TODO"
186
+ else
187
+ # p ::Extlib::Inflection.classify(name.to_s.singularize)
188
+ many_model = Object.const_get(::Extlib::Inflection.classify(name.to_s.singularize))
189
+ #p resource
190
+ #p many_model
191
+ #puts "many"
192
+ #p(parse_resource(many, many_model,
193
+ # ::DataMapper::Query.new(query.repository, many_model ))) unless many_model.nil?
194
+ set = resource.send(name)
195
+ # p set
196
+ many.elements.each do |element|
197
+ set << parse_resource(element, many_model,
198
+ ::DataMapper::Query.new(query.repository, many_model ))
199
+ end unless many_model.nil?
200
+ # p set
201
+ end
202
+ end
203
+ resource.instance_variable_set(:@new_record, false)
204
+ #p resource
205
+ resource
206
+ end
207
+
208
+ # @see BaseAdapter
209
+ def create_resource(resource)
210
+ name = resource.model.name
211
+ uri = "/#{name.pluralize}.xml"
212
+ logger.debug { "post #{uri}" }
213
+ response = http_post(uri, resource.to_xml )
214
+ logger.debug { response.body.to_s }
215
+ resource_new = parse_resource(REXML::Document::new(response.body).root,
216
+ resource.model,
217
+ ::DataMapper::Query.new(resource.repository,
218
+ resource.model ))
219
+
220
+ # copy all attributes/associations from the downloaded resource
221
+ # to the given resource
222
+ # TODO better pass the given resource into parse_resource
223
+ resource_new.attributes.each do |key, value|
224
+ resource.send(:properties)[key].set!(resource, value)
225
+ end
226
+ resource_new.send(:relationships).each do |key, value|
227
+ resource.send("#{key}=".to_sym, resource_new.send(key))
228
+ end
229
+ resource_new
230
+ end
231
+
232
+ # @see BaseAdapter
233
+ def read_resource(query)
234
+ key = key_value_from_query(query)
235
+ uri = "/#{resource_name_from_query(query).pluralize}/#{key}.xml"
236
+ logger.debug { "get #{uri}" }
237
+ response = http_get(uri)
238
+ if response.kind_of?(Net::HTTPSuccess)
239
+ logger.debug { response.body.to_s }
240
+ parse_resource(REXML::Document::new(response.body).root,
241
+ query.model,
242
+ query)
243
+ else
244
+ #TODO may act on different response codes differently
245
+ end
246
+ end
247
+
248
+ # @see BaseAdapter
249
+ def read_resources(query)
250
+ if single_entity_query?(query)
251
+ [read_resource(query)]
252
+ else
253
+ uri = "/#{resource_name_from_query(query).pluralize}.xml"
254
+ logger.debug { "get #{uri}" }
255
+ response = http_get(uri)
256
+ if response.kind_of?(Net::HTTPSuccess)
257
+ result = []
258
+ logger.debug { response.body.to_s }
259
+ REXML::Document::new(response.body).root.each do |element|
260
+ result << parse_resource(element,
261
+ query.model,
262
+ query)
263
+ end
264
+ result
265
+ else
266
+ #TODO may act on different response codes differently
267
+ end
268
+ end
269
+ end
270
+
271
+ # @overwrite BaseAdapter
272
+ def update(attributes, query)
273
+ if query.limit == 1 or single_entity_query?(query)
274
+ xml = attributes_to_xml(resource_name_from_query(query), attributes)
275
+ key = key_value_from_query(query)
276
+ uri = "/#{resource_name_from_query(query).pluralize}/#{key}.xml"
277
+ logger.debug { "put #{uri}" }
278
+ response = http_put(uri, xml)
279
+ response.kind_of?(Net::HTTPSuccess)
280
+ else
281
+ super
282
+ end
283
+ end
284
+
285
+ # @see BaseAdapter
286
+ def update_resource(resource, attributes)
287
+ query = resource.to_query
288
+ xml = attributes_to_xml(resource.name, attributes)
289
+ key = key_value_from_query(query)
290
+ logger.debug {resource.to_xml}
291
+ response = http_put("/#{resource_name_from_query(query).pluralize}/#{key}.xml", xml)
292
+ response.kind_of?(Net::HTTPSuccess)
293
+ end
294
+
295
+ # @overwrite BaseAdapter
296
+ def delete(query)
297
+ if query.limit == 1 or single_entity_query?(query)
298
+ name = resource_name_from_query(query)
299
+ key = key_value_from_query(query)
300
+ uri = "/#{name.pluralize}/#{key}.xml"
301
+ logger.debug { "delete #{uri}" }
302
+ response = http_delete(uri)
303
+ response.kind_of?(Net::HTTPSuccess)
304
+ else
305
+ super
306
+ end
307
+ end
308
+
309
+ # @see BaseAdapter
310
+ def delete_resource(resource)
311
+ name = resource.name
312
+ key = key_value_from_query(resource.to_query)
313
+ uri = "/#{name.pluralize}/#{key}.xml"
314
+ logger.debug { "delete #{uri}" }
315
+ response = http_delete(uri)
316
+ response.kind_of?(Net::HTTPSuccess)
317
+ end
318
+ end
319
+ end
320
+ end