dm-xml-adapter 0.582 → 0.584

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