dm-xml-adapter 0.582 → 0.584

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.
@@ -3,62 +3,83 @@ require 'dm-core'
3
3
  require 'builder'
4
4
  require 'dm-core/adapters/abstract_adapter'
5
5
  require 'pp'
6
+
6
7
  gem 'libxml-ruby', '>= 0.8.3'
7
8
  require 'xml'
8
9
  require 'tempfile'
9
10
  require 'simple_memoize'
10
11
  require 'log4r'
11
12
 
13
+ # http://redcorundum.blogspot.com/2006/05/kernelqualifiedconstget.html
14
+ module Kernel
15
+ def qualified_const_get(str)
16
+ path = str.to_s.split('::')
17
+ from_root = path[0].empty?
18
+ if from_root
19
+ from_root = []
20
+ path = path[1..-1]
21
+ else
22
+ start_ns = ((Class === self)||(Module === self)) ? self : self.class
23
+ from_root = start_ns.to_s.split('::')
24
+ end
25
+ until from_root.empty?
26
+ begin
27
+ return (from_root+path).inject(Object) { |ns,name| ns.const_get(name) }
28
+ rescue NameError
29
+ from_root.delete_at(-1)
30
+ end
31
+ end
32
+ path.inject(Object) { |ns,name| ns.const_get(name) }
33
+ end
34
+ end
35
+
12
36
  # the XML adapter is an adapter for DataMapper that allows you to store
13
37
  # data in XML files. beware, it's not transactionally safe.
14
38
  module DataMapper::Adapters
15
-
16
- class XmlAdapterCache
17
-
18
- def initialize
19
- @mtimes = Hash.new()
20
- @classes = Hash.new()
21
- end
22
-
23
- def set_mtime(file, mtime)
24
- @mtimes[file] = mtime
25
- end
26
-
27
- def delete_mtime(file)
39
+ class XmlAdapterCache
40
+ def initialize
41
+ @mtimes = Hash.new()
42
+ @classes = Hash.new()
43
+ end
44
+
45
+ def set_mtime(file, mtime)
46
+ @mtimes[file] = mtime
47
+ end
48
+
49
+ def delete_mtime(file)
28
50
  @mtimes.delete(file)
29
- end
30
-
31
- def get_mtime(file)
32
- return @mtimes[file]
33
- end
34
-
35
- def put(classname, id, object)
51
+ end
52
+
53
+ def get_mtime(file)
54
+ return @mtimes[file]
55
+ end
56
+
57
+ def put(classname, id, object)
36
58
  # check to see if we have a classname entry
37
- #puts "putting a cache entry of id: #{id}"
59
+ #puts "putting a cache entry of id: #{id}"
38
60
  if (@classes[classname] == nil)
39
61
  @classes[classname] = Hash.new
40
62
  end
41
-
63
+
42
64
  hash = @classes[classname]
43
65
  hash[id.to_s] = object
44
- end
45
-
46
- def delete(classname, id)
66
+ end
67
+
68
+ def delete(classname, id)
47
69
  hash = @classes[classname]
48
70
  unless hash == nil
49
71
  hash.delete(id.to_s)
50
72
  end
51
- end
52
-
53
- def get(classname, id)
54
- #puts "getting a cache entry for id: #{id}"
73
+ end
74
+
75
+ def get(classname, id)
76
+ #puts "getting a cache entry for id: #{id}"
55
77
  hash = @classes[classname]
56
78
  return hash[id]
57
- end
58
- end
59
-
60
- class XmlAdapter < AbstractAdapter
79
+ end
80
+ end
61
81
 
82
+ class XmlAdapter < AbstractAdapter
62
83
  def self.threads=(count)
63
84
  @@threadcount = count
64
85
  end
@@ -69,22 +90,22 @@ module DataMapper::Adapters
69
90
  @@threadcount = 1
70
91
  @options = Hash.new
71
92
  @options[:directory] = options[:directory]
72
- @options[:directory] ||= './db'
73
-
93
+ @options[:directory] ||= './db'
94
+
74
95
  @last_used_id = Hash.new
75
-
96
+
76
97
  @cache = XmlAdapterCache.new
77
-
98
+
78
99
  end
79
-
100
+
80
101
  def destroy_model_storage(model)
81
- FileUtils.rm_rf(classname_to_dir(model.to_s))
102
+ FileUtils.rm_rf(classname_to_dir(model.to_s))
82
103
  end
83
-
104
+
84
105
  def create_model_storage(model)
85
- FileUtils.mkdir_p(classname_to_dir(model.to_s))
106
+ FileUtils.mkdir_p(classname_to_dir(model.to_s))
86
107
  end
87
-
108
+
88
109
  def create(resources)
89
110
  key = resources.first.model.key.first.name
90
111
  resources.each do |resource|
@@ -96,55 +117,55 @@ module DataMapper::Adapters
96
117
  save(resource)
97
118
  end.size
98
119
  end
99
-
120
+
100
121
  def delete(collection)
101
- collection.each do |result|
122
+ collection.each do |result|
102
123
  key = result.key.first
103
124
  class_name = result.model.to_s
104
125
  @last_used_id[class_name] = key
105
- xml_destroy(result)
106
- # also remove from cache
107
- @cache.delete(class_name, key)
108
- # also remove from mtimes
109
- @cache.delete_mtime(class_name_to_file(class_name, key))
110
- end
111
- return collection.size
126
+ xml_destroy(result)
127
+ # also remove from cache
128
+ @cache.delete(class_name, key)
129
+ # also remove from mtimes
130
+ @cache.delete_mtime(class_name_to_file(class_name, key))
131
+ end
132
+ return collection.size
112
133
  end
113
-
134
+
114
135
  def update(attributes, collection)
115
- # ok, for each object found we have to update the attribs we found
116
- # first thing is figure out what class we are dealing with
117
- # iterate over every object in this set and set the given attributes
118
- collection.each do |obj|
119
- attributes.each do |attrib|
120
- # attrib is an array
121
- # first member is Property object
122
- # second member is the value
123
- obj.instance_variable_set("@" + attrib[0].name.to_s, attrib[1])
124
- end
125
- save(obj)
126
- end
136
+ # ok, for each object found we have to update the attribs we found
137
+ # first thing is figure out what class we are dealing with
138
+ # iterate over every object in this set and set the given attributes
139
+ collection.each do |obj|
140
+ attributes.each do |attrib|
141
+ # attrib is an array
142
+ # first member is Property object
143
+ # second member is the value
144
+ obj.instance_variable_set("@" + attrib[0].name.to_s, attrib[1])
145
+ end
146
+ save(obj)
147
+ end
127
148
  return collection
128
149
  end
129
-
150
+
130
151
  def read(query)
131
- return filter_result_set(get_all(query.model), query)
152
+ return filter_result_set(get_all(query.model), query)
132
153
  end
133
-
154
+
134
155
  private
135
-
136
- def xml_destroy(resource)
156
+
157
+ def xml_destroy(resource)
137
158
  # take an objects class and ID and figure
138
159
  # out what file it's in
139
160
  # and then remove that file
140
161
  File.unlink class_name_to_file(resource.class.to_s, resource.key.first)
141
162
  end
142
-
163
+
143
164
  def filter_result_set(objects, query)
144
165
  result_set = objects.clone
145
166
  return query.filter_records(result_set)
146
167
  end
147
-
168
+
148
169
  def get_all(model)
149
170
  model_name = model.to_s
150
171
  directory = classname_to_dir(model_name)
@@ -177,21 +198,24 @@ module DataMapper::Adapters
177
198
  cache_mtime = @cache.get_mtime(filename)
178
199
  return true if (mtime != nil and cache_mtime != nil and mtime == cache_mtime)
179
200
  end
180
-
201
+
181
202
  def file_to_id(file)
182
203
  return file.match(/([0-9]+)\.xml/)[1]
183
204
  end
184
-
205
+
206
+ def get_instance(model_name)
207
+ end
208
+
185
209
  def file_to_object(file, model)
186
210
  model_name = model.to_s
187
211
  # allocate new object to receive these fields
188
212
  if (model_name.match(/(.*)\:\:(.*)/))
189
213
  modname, clazz = [$1, $2]
190
- new_obj = Kernel.const_get(modname).const_get(clazz).new
214
+ new_obj = Kernel.qualified_const_get(model_name).new
191
215
  else
192
216
  new_obj = Kernel.const_get(model_name).new
193
217
  end
194
-
218
+
195
219
  # iterate over children
196
220
  XML::Parser.string(IO.read(file)).parse.root.children.each do |child|
197
221
  child_class = child.attributes["class"]
@@ -200,7 +224,7 @@ module DataMapper::Adapters
200
224
  populate_instance(new_obj, child, child_class)
201
225
  end
202
226
  end
203
-
227
+
204
228
  return new_obj
205
229
  end
206
230
 
@@ -221,7 +245,7 @@ module DataMapper::Adapters
221
245
  new_obj.instance_variable_set("@#{child.name}", Date.parse(child.content))
222
246
  end
223
247
  end
224
-
248
+
225
249
  def find_free_id_for(class_name)
226
250
  # if there are no entries in the directory
227
251
  # or the directory doesn't exist
@@ -249,7 +273,7 @@ module DataMapper::Adapters
249
273
  id += 1
250
274
  end
251
275
  end
252
-
276
+
253
277
  def save(resource)
254
278
  # since we're saving, purge the cache
255
279
  resource_class = resource.class.to_s
@@ -266,7 +290,7 @@ module DataMapper::Adapters
266
290
  # set up builder
267
291
  out_string = ""
268
292
  xml = Builder::XmlMarkup.new(:target => out_string, :indent => 1)
269
-
293
+
270
294
  # iterate over the resource and figure out the fields
271
295
  xml.tag!("RubyObject", :class => resource.model.to_s) do
272
296
  resource.model.properties.each do |property|
@@ -282,8 +306,8 @@ module DataMapper::Adapters
282
306
  end
283
307
  end
284
308
  end
285
-
286
- #puts "the key is now: #{resource_key}"
309
+
310
+ #puts "the key is now: #{resource_key}"
287
311
  xmlfile = File.new(class_name_to_file(resource_class, resource_key), "w")
288
312
  #puts "saving to #{xmlfile.path}"
289
313
  tempfile = Tempfile.new("dm-xml-adapter", Dir.tmpdir())
@@ -292,14 +316,14 @@ module DataMapper::Adapters
292
316
  tempfile.close
293
317
  FileUtils.mv(tempfile.path,xmlfile.path)
294
318
  return xmlfile
295
-
319
+
296
320
  end
297
321
 
298
322
  def classname_to_dir(class_name)
299
323
  return File.join(@options[:directory],
300
- class_name.gsub("/", "_").gsub(":", "_"))
324
+ class_name.gsub("/", "_").gsub(":", "_"))
301
325
  end
302
-
326
+
303
327
  def class_name_to_file(class_name, id)
304
328
  return File.join(classname_to_dir(class_name), id.to_s + ".xml")
305
329
  end
@@ -307,7 +331,7 @@ module DataMapper::Adapters
307
331
  #memoize(:file_to_id)
308
332
  #memoize(:classname_to_dir)
309
333
  #memoize(:class_name_to_file)
310
-
334
+
311
335
  end
312
336
  end
313
337
 
@@ -19,12 +19,12 @@ describe DataMapper::Adapters::XmlAdapter do
19
19
  AutoQuote.all.each {|aq| aq.destroy }
20
20
  Food.all.each {|f| f.destroy }
21
21
  Drink.all.each {|d| d.destroy }
22
+ Three::Level::Test::IsFun.all.each {|d| d.destroy }
22
23
  end
23
-
24
+
24
25
  after(:each) do
25
26
  delete_all
26
27
  end
27
-
28
28
 
29
29
  describe "CRUD" do
30
30
 
@@ -34,14 +34,14 @@ describe DataMapper::Adapters::XmlAdapter do
34
34
  AutoQuote.all.size.should == 1
35
35
  end
36
36
  end
37
-
37
+
38
38
  describe "content attribute" do
39
39
  it "should be able to handle a content attribute" do
40
40
  XMLTest::User.create(:name => "contentking", :content => "cool")
41
41
  XMLTest::User.all.size.should == 1
42
42
  end
43
43
  end
44
-
44
+
45
45
  describe "datetime" do
46
46
  it "should do datetime" do
47
47
  u1 = XMLTest::User.new
@@ -53,7 +53,7 @@ describe DataMapper::Adapters::XmlAdapter do
53
53
  end
54
54
  end
55
55
 
56
- describe "date" do
56
+ describe "date" do
57
57
  it "should do date" do
58
58
  u1 = XMLTest::User.new
59
59
  u1.name = "cool!"
@@ -82,7 +82,7 @@ describe DataMapper::Adapters::XmlAdapter do
82
82
  u2.cool.class.should == FalseClass
83
83
  end
84
84
  end
85
-
85
+
86
86
  describe "associations" do
87
87
  it "should have associations" do
88
88
  u1 = XMLTest::User.new
@@ -101,14 +101,14 @@ describe DataMapper::Adapters::XmlAdapter do
101
101
  u3.posts.size.should == 2
102
102
  end
103
103
  end
104
-
104
+
105
105
  describe "get all" do
106
106
  it "should get all" do
107
107
  XMLTest::User.create(:name => :yeah)
108
108
  XMLTest::User.all.should_not == nil
109
109
  end
110
110
  end
111
-
111
+
112
112
  describe "update" do
113
113
  it "should update" do
114
114
  u1 = XMLTest::User.new
@@ -127,7 +127,7 @@ describe DataMapper::Adapters::XmlAdapter do
127
127
  u.user_id.should_not == nil
128
128
  end
129
129
  end
130
-
130
+
131
131
  describe "delete" do
132
132
  it "should delete someone" do
133
133
  user = XMLTest::User.create
@@ -143,7 +143,7 @@ describe DataMapper::Adapters::XmlAdapter do
143
143
  user1.money.class.should == BigDecimal
144
144
  end
145
145
  end
146
-
146
+
147
147
  describe "find not" do
148
148
  it "should find someone with a not clause" do
149
149
  user1 = XMLTest::User.create(:name => "joe")
@@ -165,9 +165,16 @@ describe DataMapper::Adapters::XmlAdapter do
165
165
  Drink.first(:name => "Drinky drink!").should_not == nil
166
166
  end
167
167
  end
168
-
168
+
169
+ describe "complex class name" do
170
+ it "should be able to persist" do
171
+ fun = Three::Level::Test::IsFun.new
172
+ fun.superfun = true
173
+ fun.save
174
+ end
175
+ end
176
+
169
177
  end
170
-
171
178
 
172
179
  end
173
180
 
data/spec/spec_helper.rb CHANGED
@@ -4,49 +4,61 @@ require 'pathname'
4
4
  require 'lib/dm-xml-adapter'
5
5
 
6
6
  class Food
7
- include DataMapper::Resource
7
+ include DataMapper::Resource
8
8
 
9
- property :food_id, Serial
10
- property :name, String
9
+ property :food_id, Serial
10
+ property :name, String
11
11
  end
12
12
 
13
13
  class Drink
14
- include DataMapper::Resource
15
-
16
- property :drink_id, Serial
17
- property :name, String
14
+ include DataMapper::Resource
15
+
16
+ property :drink_id, Serial
17
+ property :name, String
18
18
  end
19
19
 
20
20
  class AutoQuote
21
- include DataMapper::Resource
22
-
23
- property :quote_id, Serial
24
- property :fullname, String
21
+ include DataMapper::Resource
22
+
23
+ property :quote_id, Serial
24
+ property :fullname, String
25
25
  end
26
26
 
27
27
  module XMLTest
28
- class Post
29
- include DataMapper::Resource
30
-
31
- property :post_id, Serial
32
- property :title, String
33
- property :created, DateTime
34
-
35
- belongs_to :user, :model => "User"
36
- end
37
-
38
- class User
39
- include DataMapper::Resource
40
-
41
- property :user_id, Serial
42
- property :name, String
43
- property :age, Integer
44
- property :money, Decimal
45
- property :created, DateTime
46
- property :cool, Boolean
47
- property :content, String
48
- property :date, Date
49
-
50
- has n, :posts, :model => "Post"
28
+ class Post
29
+ include DataMapper::Resource
30
+
31
+ property :post_id, Serial
32
+ property :title, String
33
+ property :created, DateTime
34
+
35
+ belongs_to :user, :model => "User"
36
+ end
37
+
38
+ class User
39
+ include DataMapper::Resource
40
+
41
+ property :user_id, Serial
42
+ property :name, String
43
+ property :age, Integer
44
+ property :money, Decimal
45
+ property :created, DateTime
46
+ property :cool, Boolean
47
+ property :content, String
48
+ property :date, Date
49
+
50
+ has n, :posts, :model => "Post"
51
+ end
51
52
  end
53
+
54
+ module Three
55
+ module Level
56
+ module Test
57
+ class IsFun
58
+ include DataMapper::Resource
59
+ property :fun_id, Serial
60
+ property :superfun, Boolean
61
+ end
62
+ end
63
+ end
52
64
  end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-xml-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.582"
4
+ hash: 1179
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 584
9
+ version: "0.584"
5
10
  platform: ruby
6
11
  authors:
7
12
  - Joshua Harding
@@ -9,69 +14,93 @@ autorequire: dm-xml-adapter
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-07-27 00:00:00 -04:00
17
+ date: 2011-07-18 00:00:00 -04:00
13
18
  default_executable:
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: libxml-ruby
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
20
25
  requirements:
21
26
  - - ">="
22
27
  - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
23
31
  version: "0"
24
- version:
32
+ type: :runtime
33
+ version_requirements: *id001
25
34
  - !ruby/object:Gem::Dependency
26
35
  name: builder
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
30
39
  requirements:
31
40
  - - ">="
32
41
  - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
33
45
  version: "0"
34
- version:
46
+ type: :runtime
47
+ version_requirements: *id002
35
48
  - !ruby/object:Gem::Dependency
36
49
  name: simple_memoize
37
- type: :runtime
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
40
53
  requirements:
41
54
  - - ">="
42
55
  - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
43
59
  version: "0"
44
- version:
60
+ type: :runtime
61
+ version_requirements: *id003
45
62
  - !ruby/object:Gem::Dependency
46
63
  name: log4r
47
- type: :runtime
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
50
67
  requirements:
51
68
  - - ">="
52
69
  - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
53
73
  version: "0"
54
- version:
74
+ type: :runtime
75
+ version_requirements: *id004
55
76
  - !ruby/object:Gem::Dependency
56
77
  name: dm-core
57
- type: :runtime
58
- version_requirement:
59
- version_requirements: !ruby/object:Gem::Requirement
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ none: false
60
81
  requirements:
61
82
  - - ">="
62
83
  - !ruby/object:Gem::Version
84
+ hash: 3
85
+ segments:
86
+ - 0
63
87
  version: "0"
64
- version:
88
+ type: :runtime
89
+ version_requirements: *id005
65
90
  - !ruby/object:Gem::Dependency
66
91
  name: dm-migrations
67
- type: :runtime
68
- version_requirement:
69
- version_requirements: !ruby/object:Gem::Requirement
92
+ prerelease: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
94
+ none: false
70
95
  requirements:
71
96
  - - ">="
72
97
  - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
73
101
  version: "0"
74
- version:
102
+ type: :runtime
103
+ version_requirements: *id006
75
104
  description:
76
105
  email: josh@statewidesoftware.com
77
106
  executables: []
@@ -96,21 +125,27 @@ rdoc_options: []
96
125
  require_paths:
97
126
  - lib
98
127
  required_ruby_version: !ruby/object:Gem::Requirement
128
+ none: false
99
129
  requirements:
100
130
  - - ">="
101
131
  - !ruby/object:Gem::Version
132
+ hash: 3
133
+ segments:
134
+ - 0
102
135
  version: "0"
103
- version:
104
136
  required_rubygems_version: !ruby/object:Gem::Requirement
137
+ none: false
105
138
  requirements:
106
139
  - - ">="
107
140
  - !ruby/object:Gem::Version
141
+ hash: 3
142
+ segments:
143
+ - 0
108
144
  version: "0"
109
- version:
110
145
  requirements: []
111
146
 
112
147
  rubyforge_project:
113
- rubygems_version: 1.3.5
148
+ rubygems_version: 1.3.7
114
149
  signing_key:
115
150
  specification_version: 3
116
151
  summary: a XML adapter for DataMapper. this adapter allows you to use DataMapper with XML files as a backing store.