datamapper4rails 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|