datamapper4rails 0.3.0
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/History.txt +6 -0
- data/Manifest.txt +37 -0
- data/README.txt +151 -0
- data/Rakefile +48 -0
- data/datamapper_rails_templates.rb +114 -0
- data/generators/datamapper_install/datamapper_install_generator.rb +12 -0
- data/generators/datamapper_install/templates/datamapper.rake +88 -0
- data/generators/datamapper_model/datamapper_model_generator.rb +18 -0
- data/generators/datamapper_model/templates/migration.rb +18 -0
- data/generators/datamapper_model/templates/model.rb +14 -0
- data/generators/datamapper_rspec_model/datamapper_rspec_model_generator.rb +18 -0
- data/generators/datamapper_rspec_model/templates/model_spec.rb +44 -0
- data/generators/datamapper_rspec_scaffold/datamapper_rspec_scaffold_generator.rb +20 -0
- data/generators/datamapper_rspec_scaffold/templates/controller_spec.rb +171 -0
- data/generators/datamapper_rspec_scaffold/templates/edit_erb_spec.rb +25 -0
- data/generators/datamapper_scaffold/datamapper_scaffold_generator.rb +31 -0
- data/generators/datamapper_scaffold/templates/controller.rb +90 -0
- data/generators/datamapper_scaffold/templates/functional_test.rb +49 -0
- data/generators/datamapper_scaffold/templates/view_edit.html.erb +18 -0
- data/generators/datamapper_scaffold/templates/view_index.html.erb +24 -0
- data/generators/datamapper_scaffold/templates/view_new.html.erb +17 -0
- data/generators/datamapper_scaffold/templates/view_show.html.erb +10 -0
- data/lib/datamapper4rails.rb +14 -0
- data/lib/datamapper4rails/adapters/base_adapter.rb +198 -0
- data/lib/datamapper4rails/adapters/restful_adapter.rb +320 -0
- data/lib/datamapper4rails/datamapper_store.rb +28 -0
- data/lib/datamapper4rails/identity_maps.rb +25 -0
- data/lib/datamapper4rails/integration_test.rb +45 -0
- data/lib/datamapper4rails/overlay.rb +69 -0
- data/lib/datamapper4rails/preload_models.rb +26 -0
- data/lib/datamapper4rails/restful_transactions.rb +43 -0
- data/lib/datamapper4rails/rspec.rb +8 -0
- data/lib/datamapper4rails/rspec_default_values.rb +23 -0
- data/lib/datamapper4rails/version.rb +3 -0
- data/spec/datamapper_store_spec.rb +23 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +34 -0
- 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
|