datamapper4rail 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -18,5 +18,11 @@ lib/datamapper4rails/adapters/base_adapter.rb
18
18
  lib/datamapper4rails/adapters/restful_adapter.rb
19
19
  lib/datamapper4rails/database_config.rb
20
20
  lib/datamapper4rails/datamapper_store.rb
21
+ lib/datamapper4rails/identity_maps.rb
22
+ lib/datamapper4rails/preload_models.rb
21
23
  lib/datamapper4rails/restful_transactions.rb
22
24
  lib/datamapper4rails/version.rb
25
+ spec/datamapper_store_spec.rb
26
+ spec/restful_adapter_spec.rb
27
+ spec/spec.opts
28
+ spec/spec_helper.rb
data/Rakefile CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'hoe'
5
+
6
+ require 'spec'
7
+ require 'spec/rake/spectask'
8
+ require 'pathname'
9
+
5
10
  require './lib/datamapper4rails/version.rb'
6
11
 
7
12
  Hoe.new('datamapper4rail', Datamapper4rails::VERSION) do |p|
@@ -17,16 +22,16 @@ task :install => [:clean, :package] do
17
22
  sh "gem install --local #{gem} --no-ri --no-rdoc"
18
23
  end
19
24
 
20
- # desc 'Run specifications'
21
- # Spec::Rake::SpecTask.new(:spec) do |t|
22
- # if File.exists?('spec/spec.opts')
23
- # t.spec_opts << '--options' << 'spec/spec.opts'
24
- # end
25
- # t.spec_files = Pathname.glob('./spec/**/*_spec.rb')
26
- # end
25
+ desc 'Run specifications'
26
+ Spec::Rake::SpecTask.new(:spec) do |t|
27
+ if File.exists?('spec/spec.opts')
28
+ t.spec_opts << '--options' << 'spec/spec.opts'
29
+ end
30
+ t.spec_files = Pathname.glob('./spec/**/*_spec.rb')
31
+ end
27
32
 
28
- # require 'yard'
33
+ require 'yard'
29
34
 
30
- # YARD::Rake::YardocTask.new
35
+ YARD::Rake::YardocTask.new
31
36
 
32
37
  # vim: syntax=Ruby
@@ -2,13 +2,13 @@ require 'rails_generator/generators/components/model/model_generator'
2
2
  require 'active_record'
3
3
  require File.dirname(__FILE__) + '/../rspec_default_values'
4
4
 
5
- class RspecDmModelExtendedGenerator <ModelGenerator
5
+ class RspecDmModelGenerator <ModelGenerator
6
6
 
7
7
  def manifest
8
8
  record do |m|
9
9
 
10
10
  # Check for class naming collisions.
11
- m.class_collisions class_path, class_name
11
+ #m.class_collisions class_path, class_name
12
12
 
13
13
  # Model, spec, and fixture directories.
14
14
  m.directory File.join('app/models', class_path)
@@ -1,16 +1,19 @@
1
1
  class <%= class_name %>
2
2
  include DataMapper::Resource
3
+ <% if options[:add_constraints] -%>
4
+ include DataMapper::Constraints
5
+ <% end -%>
6
+
3
7
  property :id, Serial
4
8
 
5
9
  <% for attribute in attributes -%>
6
- property :<%= attribute.name %>, <%= attribute.type.to_s.camelize %>, :nullable => false <% if attribute.type == :string or attribute.type == :text -%>, :format => /^[^<'&">]*$/<% if attribute.type == :string %>, :length => 50<% end -%>
7
- <% else -%>
10
+ property :<%= attribute.name %>, <%= attribute.type.to_s.camelize %>, :nullable => false <% if attribute.type == :string or attribute.type == :text -%>, :format => /^[^<'&">]*$/<% if attribute.type == :string %>, :length => 255<% end -%>
11
+ <% #else -%>
8
12
 
9
13
  <% end -%>
10
14
  <% end -%>
11
15
  <% unless options[:skip_timestamps] %>
12
- property :created_at, DateTime, :nullable => false
13
- property :updated_at, DateTime, :nullable => false
16
+ timestamps :at
14
17
 
15
18
  <% end -%>
16
19
  end
@@ -1,53 +1 @@
1
- require 'dm-core'
2
- def config_file()
3
- RAILS_ROOT + "/config/database.yml"
4
- end
5
-
6
- def create_connection()
7
- conf = config.dup
8
- if repositories = conf.delete(:repositories)
9
- repositories.each do |repo, conf|
10
- ::DataMapper.setup(repo, conf) unless conf.empty?
11
- end
12
- else
13
- ::DataMapper.setup(:default, conf) unless conf.empty?
14
- end
15
- end
16
-
17
- def get_config_for_environment
18
- if hash = full_config[RAILS_ENV]
19
- symbolize_keys(hash)
20
- elsif hash = full_config[RAILS_ENV.to_sym]
21
- hash
22
- else
23
- raise ArgumentError, "missing environment '#{RAILS_ENV}' in config file #{config_file}"
24
- end
25
- end
26
-
27
- def full_config
28
- @full_config ||= YAML::load(ERB.new(IO.read(config_file)).result)
29
- end
30
-
31
- def config
32
- @config ||= get_config_for_environment
33
- end
34
-
35
- def symbolize_keys(h)
36
- config = {}
37
-
38
- h.each do |k, v|
39
- if k == 'port'
40
- config[k.to_sym] = v.to_i
41
- elsif k == 'adapter' && v == 'postgresql'
42
- config[k.to_sym] = 'postgres'
43
- elsif v.is_a?(Hash)
44
- config[k.to_sym] = symbolize_keys(v)
45
- else
46
- config[k.to_sym] = v
47
- end
48
- end
49
-
50
- config
51
- end
52
-
53
- create_connection()
1
+ require 'datamapper4rails/database_config'
@@ -1,7 +1,8 @@
1
- require 'adapters/restful_adapter'
1
+ require 'datamapper4rails/adapters/base_adapter'
2
2
  require 'net/http'
3
3
  require 'extlib/inflection'
4
4
  require 'extlib/module'
5
+ require 'dm-serializer'
5
6
 
6
7
  module DataMapper
7
8
  module Adapters
@@ -44,6 +45,18 @@ module DataMapper
44
45
  raise "compound keys are not supported"
45
46
  end
46
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
47
60
 
48
61
  def http_get(uri)
49
62
  send_request do |http|
@@ -66,13 +79,16 @@ module DataMapper
66
79
  end
67
80
  end
68
81
 
69
- def http_put(uri, data = {})
82
+ def http_put(uri, data = nil)
70
83
  send_request do |http|
71
- request = Net::HTTP::Put.new(uri)
84
+ request = Net::HTTP::Put.new(uri, {
85
+ 'content-type' => 'application/xml',
86
+ 'content-length' => data.length.to_s
87
+ })
72
88
  request.basic_auth(@uri[:login],
73
89
  @uri[:password]) unless @uri[:login].blank?
74
- request.set_form_data(data)
75
- http.request(request)
90
+ # request.set_form_data(data)
91
+ http.request(request, data)
76
92
  end
77
93
  end
78
94
 
@@ -112,14 +128,25 @@ module DataMapper
112
128
  #puts
113
129
  #puts "elements"
114
130
  #p elements
131
+ #p query
132
+ #p model
115
133
  resource = model.load(model.properties.collect do |f|
116
134
  elements[f.name]
117
135
  end, query)
118
136
  resource.send("#{keys_from_query(query)[0].name}=".to_sym, elements[keys_from_query(query)[0].name] )
119
- #p resource
120
- associations.each do |name, association|
121
- model =
137
+ # p resource
138
+ #p associations
139
+ associations.each do |name, association|
140
+ # puts "asso"
141
+ # p model
142
+ # p name
143
+ # p association
144
+ #p model.relationships
145
+ is_one_to_one = false
146
+ asso_model =
122
147
  if rel = model.relationships[name]
148
+ #puts "rel"
149
+ #p rel
123
150
  if rel.child_model == model
124
151
  rel.parent_model
125
152
  else
@@ -129,17 +156,38 @@ module DataMapper
129
156
  #::Extlib::Inflection.constantize(::Extlib::Inflection.classify(name))
130
157
  # model.find_const(::Extlib::Inflection.classify(name))
131
158
  end
159
+ # p asso_model
132
160
  if resource.respond_to? "#{name}=".to_sym
161
+ # puts
162
+ # puts "association"
163
+ # puts name
164
+ # p model
165
+ # p asso_model
133
166
  resource.send("#{name}=".to_sym,
134
- parse_resource(association, model,
135
- ::DataMapper::Query.new(query.repository, model )))
167
+ parse_resource(association, asso_model,
168
+ ::DataMapper::Query.new(query.repository, asso_model ))) unless asso_model.nil?
136
169
  else
137
170
  resource.send(("#{name.to_s.pluralize}<" + "<").to_sym,
138
- parse_resource(association, model,
139
- ::DataMapper::Query.new(query.repository, model )))
171
+ parse_resource(association, asso_model,
172
+ ::DataMapper::Query.new(query.repository, asso_model ))) unless asso_model.nil?
173
+ end
174
+ end
175
+
176
+ #puts "many 2 many"
177
+ #p many_to_many
178
+ many_to_many.each do |name, many|
179
+ if model.relationships[name]
180
+ # TODO
181
+ else
182
+ # p ::Extlib::Inflection.classify(name.to_s.singularize)
183
+ many_model = Object.const_get(::Extlib::Inflection.classify(name.to_s.singularize))
184
+ resource.send(name).send(("<" + "<").to_sym,
185
+ parse_resource(many, many_model,
186
+ ::DataMapper::Query.new(query.repository, many_model ))) unless many_model.nil?
140
187
  end
141
188
  end
142
189
  resource.instance_variable_set(:@new_record, false)
190
+ #p resource
143
191
  resource
144
192
  end
145
193
 
@@ -168,65 +216,70 @@ module DataMapper
168
216
 
169
217
  # @see BaseAdapter
170
218
  def read_resource(query)
171
- if(query.conditions.empty?)
172
- raise "not implemented"
219
+ key = key_value_from_query(query)
220
+ uri = "/#{resource_name_from_query(query).pluralize}/#{key}.xml"
221
+ logger.debug { "get #{uri}" }
222
+ response = http_get(uri)
223
+ if response.kind_of?(Net::HTTPSuccess)
224
+ logger.debug { response.body.to_s }
225
+ parse_resource(REXML::Document::new(response.body).root,
226
+ query.model,
227
+ query)
173
228
  else
174
- key = key_value_from_query(query)
175
- uri = "/#{resource_name_from_query(query).pluralize}/#{key}.xml"
229
+ #TODO may act on different response codes differently
230
+ end
231
+ end
232
+
233
+ # @see BaseAdapter
234
+ def read_resources(query)
235
+ if single_entity_query?(query)
236
+ [read_resource(query)]
237
+ else
238
+ uri = "/#{resource_name_from_query(query).pluralize}.xml"
176
239
  logger.debug { "get #{uri}" }
177
240
  response = http_get(uri)
178
241
  if response.kind_of?(Net::HTTPSuccess)
179
- parse_resource(REXML::Document::new(response.body).root,
180
- query.model,
181
- query)
242
+ result = []
243
+ logger.debug { response.body.to_s }
244
+ REXML::Document::new(response.body).root.each do |element|
245
+ result << parse_resource(element,
246
+ query.model,
247
+ query)
248
+ end
249
+ result
182
250
  else
183
251
  #TODO may act on different response codes differently
184
252
  end
185
253
  end
186
254
  end
187
255
 
188
- # @see BaseAdapter
189
- def read_resources(query)
190
- # raise "not implemented"
191
- [read_resource(query)]
192
- end
193
-
194
256
  # @overwrite BaseAdapter
195
257
  def update(attributes, query)
196
- name = resource_name_from_query(query)
197
- params = {}
198
- attributes.each do |attr, val|
199
- params["#{name}[#{attr.name}]"]=val
258
+ if query.limit == 1 or single_entity_query?(query)
259
+ xml = attributes_to_xml(resource_name_from_query(query), attributes)
260
+ key = key_value_from_query(query)
261
+ uri = "/#{resource_name_from_query(query).pluralize}/#{key}.xml"
262
+ logger.debug { "put #{uri}" }
263
+ response = http_put(uri, xml)
264
+ response.kind_of?(Net::HTTPSuccess)
265
+ else
266
+ super
200
267
  end
201
- key = key_value_from_query(query)
202
- uri = "/#{name.pluralize}/#{key}.xml"
203
- logger.debug { "put #{uri}" }
204
- response = http_put(uri, params)
205
- response.kind_of?(Net::HTTPSuccess)
206
268
  end
207
269
 
208
270
  # @see BaseAdapter
209
271
  def update_resource(resource, attributes)
210
272
  query = resource.to_query
211
- if(query.conditions.empty?)
212
- raise "not implemented"
213
- else
214
- name = resource.name
215
- params = {}
216
- attributes.each do |attr, val|
217
- params["#{name}[#{attr.name}]"]=val
218
- end
219
- key = key_value_from_query(query)
220
- logger.debug {resource.to_xml}
221
- response = http_put("/#{resource_name_from_query(query).pluralize}/#{key}.xml", params)
222
- response.kind_of?(Net::HTTPSuccess)
223
- end
273
+ xml = attributes_to_xml(resource.name, attributes)
274
+ key = key_value_from_query(query)
275
+ logger.debug {resource.to_xml}
276
+ response = http_put("/#{resource_name_from_query(query).pluralize}/#{key}.xml", xml)
277
+ response.kind_of?(Net::HTTPSuccess)
224
278
  end
225
-
279
+
226
280
  # @overwrite BaseAdapter
227
281
  def delete(query)
228
- # TODO limit == 1 is NOT sufficient ONLY necessary
229
- if query.limit == 1
282
+ if query.limit == 1 or single_entity_query?(query)
230
283
  name = resource_name_from_query(query)
231
284
  key = key_value_from_query(query)
232
285
  uri = "/#{name.pluralize}/#{key}.xml"
@@ -241,7 +294,7 @@ module DataMapper
241
294
  # @see BaseAdapter
242
295
  def delete_resource(resource)
243
296
  name = resource.name
244
- key = key_value_from_query(resource.to_queryquery)
297
+ key = key_value_from_query(resource.to_query)
245
298
  uri = "/#{name.pluralize}/#{key}.xml"
246
299
  logger.debug { "delete #{uri}" }
247
300
  response = http_delete(uri)
@@ -6,8 +6,13 @@ end
6
6
 
7
7
  def create_connection()
8
8
  conf = config.dup
9
- repositories = conf.delete(:repositories)
10
- ::DataMapper.setup(:default, conf) unless conf.empty?
9
+ if repositories = conf.delete(:repositories)
10
+ repositories.each do |repo, conf|
11
+ ::DataMapper.setup(repo, conf) unless conf.empty?
12
+ end
13
+ else
14
+ ::DataMapper.setup(:default, conf) unless conf.empty?
15
+ end
11
16
  end
12
17
 
13
18
  def get_config_for_environment
@@ -8,8 +8,10 @@ module ActionController
8
8
  super
9
9
  if options.delete(:cache)
10
10
  @@cache = {}
11
+ else
12
+ @@cache = nil unless self.class.class_variable_defined? :@@cache
11
13
  end
12
- @@session_class = ::DatamapperStore::Session
14
+ @@session_class = options.delete(:session_class) || ::DatamapperStore::Session unless (self.class.class_variable_defined? :@@session_class and @@session_class)
13
15
  end
14
16
 
15
17
  private
@@ -32,10 +34,8 @@ module ActionController
32
34
  @@session_class.get(sid)
33
35
  end || @@session_class.new(:session_id => sid)
34
36
  session.data = session_data || {}
35
- if session.new_record?
36
- session.updated_at = Time.now
37
- @@cache[sid] = session if @@cache
38
- end
37
+ session.updated_at = Time.now if session.dirty?
38
+ @@cache[sid] = session if @@cache
39
39
  session.save
40
40
  end
41
41
  end
@@ -60,6 +60,7 @@ module DatamapperStore
60
60
  def data=(data)
61
61
  attribute_set(:data, ::Base64.encode64(Marshal.dump(data)))
62
62
  end
63
+
63
64
  def data
64
65
  Marshal.load(::Base64.decode64(attribute_get(:data)))
65
66
  end
@@ -0,0 +1,23 @@
1
+ module Datamapper4rails
2
+ module IdentityMaps
3
+
4
+ module Base
5
+ def self.included(base)
6
+ base.prepend_around_filter(IdentityMapFilter)
7
+ end
8
+ end
9
+
10
+ class IdentityMapFilter
11
+
12
+ def self.filter(controller)
13
+ DataMapper.repository(:default) do |*block_args|
14
+ if block_given?
15
+ yield (*block_args)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ ::ActionController::Base.send(:include, Datamapper4rails::IdentityMaps::Base)
@@ -0,0 +1,26 @@
1
+ # load all models before each request so relations in datamapper find their classes
2
+ MODELS = []
3
+ Dir[RAILS_ROOT + "/app/models/**/*.rb"].each do |model|
4
+ model.sub!(/.*models\//, '').sub!(/.rb/, '')
5
+ m = ::Extlib::Inflection.classify(model.to_s)
6
+ MODELS << m
7
+ Object.const_get(m)
8
+ end
9
+
10
+ module ModelLoader
11
+ module Base
12
+ def self.included(base)
13
+ base.prepend_before_filter(ModelLoaderFilter)
14
+ end
15
+ end
16
+
17
+ class ModelLoaderFilter
18
+ def self.filter(controller)
19
+ MODELS.each do |model|
20
+ Object.const_get(model)
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ ::ActionController::Base.send(:include, ModelLoader::Base)
@@ -11,17 +11,18 @@ module Datamapper4rails
11
11
  end
12
12
 
13
13
  class TransactionFilter
14
+
14
15
  def self.filter(controller)
15
16
  case controller.request.method
16
17
  when :post, :put, :delete then
17
18
  begin
19
+ # TODO remove the :default repository and make it more general
18
20
  DataMapper::Transaction.new(DataMapper.repository(:default)) do |*block_args|
19
21
  if block_given?
20
22
  yield (*block_args)
21
23
  # added rollback for all actions which just render
22
- # a page with validation errors and do not redirect to new idem potent
23
- # page (http-method get is idem potent within the
24
- # restful paradigma
24
+ # a page (with validation errors) and do not redirect to
25
+ # another page
25
26
  unless controller.response.redirected_to
26
27
  raise Datamapper4rails::RestfulTransactions::Rollback
27
28
  end
@@ -1,3 +1,3 @@
1
1
  class Datamapper4rails
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -0,0 +1,127 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+ require 'spec_helper'
3
+ require 'datamapper4rails/datamapper_store'
4
+
5
+ describe DatamapperStore do
6
+
7
+ before :each do
8
+ load 'lib/datamapper4rails/datamapper_store.rb'
9
+ ActionController::Session::DatamapperStore.send(:class_variable_set, :@@session_class, nil)
10
+ end
11
+
12
+ it 'should initialize with no cache and default session class' do
13
+ store = ActionController::Session::DatamapperStore.new(nil)
14
+ store.class.send(:class_variable_get, :@@cache).should be_nil
15
+ store.class.send(:class_variable_get, :@@session_class).should == DatamapperStore::Session
16
+
17
+ store = ActionController::Session::DatamapperStore.new(nil, :session_class => :some_class)
18
+ store.class.send(:class_variable_get, :@@cache).should be_nil
19
+ store.class.send(:class_variable_get, :@@session_class).should == DatamapperStore::Session
20
+ end
21
+
22
+ it 'should initialize with cache and default session class' do
23
+ store = ActionController::Session::DatamapperStore.new(nil, :cache => true)
24
+ store.class.send(:class_variable_get, :@@cache).instance_of?(Hash).should be_true
25
+
26
+ store = ActionController::Session::DatamapperStore.new(nil)
27
+ store.class.send(:class_variable_get, :@@cache).instance_of?(Hash).should be_true
28
+ end
29
+
30
+ it 'should initialize with custom session class' do
31
+ store = ActionController::Session::DatamapperStore.new(nil, :session_class => Session)
32
+ store.class.send(:class_variable_get, :@@session_class).should == Session
33
+
34
+ store = ActionController::Session::DatamapperStore.new(nil, :session_class => :some_class)
35
+ store.class.send(:class_variable_get, :@@session_class).should == Session
36
+ end
37
+ end
38
+
39
+ describe 'DatamapperStore without cache' do
40
+
41
+ def mock_session(stubs={})
42
+ @mock_session ||= mock(Session, stubs)
43
+ end
44
+
45
+ before :each do
46
+ load 'lib/datamapper4rails/datamapper_store.rb'
47
+ ActionController::Session::DatamapperStore.send(:class_variable_set, :@@cache, nil)
48
+ ActionController::Session::DatamapperStore.send(:class_variable_set, :@@session_class, nil)
49
+ @store = ActionController::Session::DatamapperStore.new(nil, :session_class => Session)
50
+ end
51
+
52
+ it 'should get the session data' do
53
+ Session.stub!(:get)
54
+ @store.send(:get_session, nil, "sid").should == ["sid",{}]
55
+ Session.stub!(:get).and_return(mock_session)
56
+ mock_session.should_receive(:data).and_return({:id => "id"})
57
+ @store.send(:get_session, nil, "sid").should == ["sid",{:id => "id"}]
58
+ end
59
+
60
+ it 'should set the session data on new session' do
61
+ Session.should_receive(:get)
62
+ Session.should_receive(:new).with(:session_id => "sid").and_return(mock_session)
63
+ mock_session.should_receive(:data=).with({})
64
+ mock_session.should_receive(:dirty?).and_return(true)
65
+ mock_session.should_receive(:updated_at=)
66
+ mock_session.should_receive(:save).and_return(true)
67
+ @store.send(:set_session, nil, "sid", {}).should == true
68
+ end
69
+
70
+ it 'should set the session data' do
71
+ Session.should_receive(:get).and_return(mock_session)
72
+ mock_session.should_receive(:data=).with({})
73
+ mock_session.should_receive(:dirty?).and_return(true)
74
+ mock_session.should_receive(:updated_at=)
75
+ mock_session.should_receive(:save).and_return(true)
76
+ @store.send(:set_session, nil, "sid", {}).should == true
77
+ end
78
+ end
79
+
80
+ describe 'DatamapperStore with cache' do
81
+
82
+ def mock_session(stubs={})
83
+ @mock_session ||= mock(Session, stubs)
84
+ end
85
+
86
+ before :each do
87
+ load 'lib/datamapper4rails/datamapper_store.rb'
88
+ ActionController::Session::DatamapperStore.send(:class_variable_set, :@@cache, nil)
89
+ ActionController::Session::DatamapperStore.send(:class_variable_set, :@@session_class, nil)
90
+ @store = ActionController::Session::DatamapperStore.new(nil, :cache => true, :session_class => Session)
91
+ end
92
+
93
+ it 'should get the session data from storage' do
94
+ Session.stub!(:get)
95
+ @store.send(:get_session, nil, "sid").should == ["sid",{}]
96
+ Session.stub!(:get).and_return(mock_session)
97
+ mock_session.should_receive(:data).and_return({:id => "id"})
98
+ @store.send(:get_session, nil, "sid").should == ["sid",{:id => "id"}]
99
+ end
100
+
101
+ it 'should get the session data from cache' do
102
+ ActionController::Session::DatamapperStore.send(:class_variable_get, :@@cache)["sid"] = mock_session
103
+ mock_session.should_receive(:data).and_return({:id => "id"})
104
+ @store.send(:get_session, nil, "sid").should == ["sid",{:id => "id"}]
105
+ end
106
+
107
+ it 'should set the session data on new session' do
108
+ Session.should_receive(:get)
109
+ Session.should_receive(:new).with(:session_id => "sid").and_return(mock_session)
110
+ mock_session.should_receive(:data=).with({})
111
+ mock_session.should_receive(:dirty?).and_return(true)
112
+ mock_session.should_receive(:updated_at=)
113
+ mock_session.should_receive(:save).and_return(true)
114
+ @store.send(:set_session, nil, "sid", {}).should == true
115
+ ActionController::Session::DatamapperStore.send(:class_variable_get, :@@cache)["sid"].should == mock_session
116
+
117
+ end
118
+
119
+ it 'should set the session data' do
120
+ Session.should_receive(:get).and_return(mock_session)
121
+ mock_session.should_receive(:data=).with({})
122
+ mock_session.should_receive(:dirty?).and_return(false)
123
+ mock_session.should_receive(:save).and_return(true)
124
+ @store.send(:set_session, nil, "sid", {}).should == true
125
+ ActionController::Session::DatamapperStore.send(:class_variable_get, :@@cache)["sid"].should == mock_session
126
+ end
127
+ end
@@ -0,0 +1,187 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+ require 'spec_helper'
3
+ require 'datamapper4rails/adapters/restful_adapter'
4
+ require 'slf4r/ruby_logger'
5
+
6
+ class Item
7
+ include DataMapper::Resource
8
+
9
+ property :id, Serial
10
+ property :name, String
11
+
12
+ belongs_to :container
13
+ end
14
+ class User
15
+ include DataMapper::Resource
16
+
17
+ property :id, Serial
18
+
19
+ belongs_to :container
20
+ has n, :groups, :through => Resource
21
+ end
22
+ class Group
23
+ include DataMapper::Resource
24
+
25
+ property :id, Serial
26
+
27
+ has n, :users, :through => Resource
28
+ end
29
+
30
+ class Container
31
+ include DataMapper::Resource
32
+
33
+ property :id, Serial
34
+
35
+ has 1, :user
36
+ has n, :items
37
+ end
38
+
39
+ def mock_attribute(name)
40
+ attr = Object.new
41
+ def attr.name
42
+ @name
43
+ end
44
+ def attr.name=(name)
45
+ @name = name
46
+ end
47
+ attr.name= name
48
+ attr
49
+ end
50
+
51
+ def mock_item(stubs={})
52
+ @mock_item ||= mock(Item, stubs)
53
+ end
54
+
55
+ def mock_query(stubs={})
56
+ @mock_query ||= mock(DataMapper::Query, stubs)
57
+ end
58
+
59
+ describe DataMapper::Adapters::RestfulAdapter do
60
+
61
+ before :each do
62
+ @adapter = DataMapper::Adapters::RestfulAdapter.new(:name, "uri://")
63
+
64
+ def @adapter.key_value_from_query(query)
65
+ 432
66
+ end
67
+ def @adapter.resource_name_from_query(query)
68
+ "item"
69
+ end
70
+ def @adapter.http_put(uri, data)
71
+ @uri = uri
72
+ @data = data
73
+ end
74
+ def @adapter.http_delete(uri)
75
+ @uri = uri
76
+ end
77
+ def @adapter.data
78
+ @data
79
+ end
80
+ def @adapter.uri
81
+ @uri
82
+ end
83
+ def @adapter.body=(b)
84
+ @body = b
85
+ end
86
+ def @adapter.send_request
87
+ res = Object.new
88
+ def res.body=(b)
89
+ @body = b
90
+ end
91
+ def res.body
92
+ @body
93
+ end
94
+ def res.kind_of?(clazz)
95
+ true
96
+ end
97
+ res.body= @body
98
+ res
99
+ end
100
+
101
+ end
102
+
103
+ it 'should create an Item' do
104
+ @adapter.body = "<item><id>123</id><name>zappa</name></item>"
105
+
106
+ item = Item.new
107
+ @adapter.create_resource(item).should == item
108
+ item.id.should == 123
109
+ item.name.should == 'zappa'
110
+ end
111
+
112
+ it 'should update an Item' do
113
+ mock_item.should_receive(:to_query)
114
+ mock_item.should_receive(:name).and_return("item")
115
+ mock_item.should_receive(:to_xml)
116
+
117
+ @adapter.update_resource(mock_item, mock_attribute(:name) => "frank zappa")
118
+
119
+ @adapter.data.should == "<item><name>frank zappa</name></item>"
120
+ end
121
+
122
+ it 'should update Items' do
123
+ mock_query.should_receive(:limit).and_return(1)
124
+ @adapter.update({mock_attribute(:name) => "frank zappa"}, mock_query)
125
+
126
+ @adapter.data.should == "<item><name>frank zappa</name></item>"
127
+ end
128
+
129
+ it 'should delete an Item' do
130
+ mock_item.should_receive(:name).and_return("item")
131
+ mock_item.should_receive(:to_query)
132
+ @adapter.delete_resource(mock_item)
133
+ @adapter.uri.should == "/items/432.xml"
134
+ end
135
+
136
+ it 'should delete Items' do
137
+ mock_query.should_receive(:limit).and_return(1)
138
+ @adapter.delete(mock_query)
139
+
140
+ @adapter.uri.should == "/items/432.xml"
141
+ end
142
+
143
+ it 'should read an Item' do
144
+ @adapter.body = "<item><id>123</id><name>zappa</name></item>"
145
+
146
+ query = DataMapper::Query.new(Item.new.repository, Item)
147
+ item = @adapter.read_resource(query)
148
+ item.id.should == 123
149
+ item.name.should == 'zappa'
150
+ end
151
+
152
+ it 'should read Items' do
153
+ @adapter.body = "<items type='array'><item><id>123</id><name>zappa</name></item></items>"
154
+
155
+ query = DataMapper::Query.new(Item.new.repository, Item)
156
+ items = @adapter.read_resources(query)
157
+ items.size.should == 1
158
+ items[0].id.should == 123
159
+ items[0].name.should == 'zappa'
160
+ end
161
+ #end
162
+
163
+
164
+ #describe 'associations of ' + DataMapper::Adapters::RestfulAdapter.to_s do
165
+ it 'should read nested resource (belongs_to)' do
166
+ @adapter.body = "<item><id>123</id><name>zappa</name>" +
167
+ "<container><id>342</id>" + #<items tpye='array'><item><id>1234</id><name>frank zappa</name></item></items>" +
168
+ "</container>" +
169
+ "</item>"
170
+
171
+ query = DataMapper::Query.new(Item.new.repository, Item)
172
+ item = @adapter.read_resource(query)
173
+ item.id.should == 123
174
+ item.name.should == 'zappa'
175
+ item.container.id.should == 342
176
+ end
177
+
178
+ # it 'should read nested resource (has 1)' do
179
+ # @adapter.body = "<container><id>342</id>" +
180
+ # "<user><id>543</id></user>" +
181
+ # "</container>"
182
+
183
+ # query = DataMapper::Query.new(Container.new.repository, Container)
184
+ # c = @adapter.read_resource(query)
185
+ # c.id.should == 342
186
+ # end
187
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'dm-core'
3
+ $LOAD_PATH << Pathname(__FILE__).dirname.parent.expand_path + 'lib'
4
+
5
+ # just define a empty abstract store
6
+ module ActionController
7
+ module Session
8
+ class AbstractStore
9
+ def initialize(app, options = {})
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ class Session
16
+
17
+ include ::DataMapper::Resource
18
+
19
+ property :session_id, String, :key => true
20
+
21
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datamapper4rail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mkristian
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-21 00:00:00 +05:30
12
+ date: 2009-03-28 00:00:00 +05:30
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -64,8 +64,14 @@ files:
64
64
  - lib/datamapper4rails/adapters/restful_adapter.rb
65
65
  - lib/datamapper4rails/database_config.rb
66
66
  - lib/datamapper4rails/datamapper_store.rb
67
+ - lib/datamapper4rails/identity_maps.rb
68
+ - lib/datamapper4rails/preload_models.rb
67
69
  - lib/datamapper4rails/restful_transactions.rb
68
70
  - lib/datamapper4rails/version.rb
71
+ - spec/datamapper_store_spec.rb
72
+ - spec/restful_adapter_spec.rb
73
+ - spec/spec.opts
74
+ - spec/spec_helper.rb
69
75
  has_rdoc: true
70
76
  homepage: http://datamapper4rail.rubyforge.org
71
77
  post_install_message: