dm-xml-adapter 0.59 → 0.571
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/README +0 -1
- data/lib/dm-xml-adapter.rb +197 -201
- data/spec/dm-xml-adapter_spec.rb +14 -49
- data/spec/spec_helper.rb +34 -47
- metadata +57 -123
data/README
CHANGED
data/lib/dm-xml-adapter.rb
CHANGED
@@ -3,330 +3,326 @@ require 'dm-core'
|
|
3
3
|
require 'builder'
|
4
4
|
require 'dm-core/adapters/abstract_adapter'
|
5
5
|
require 'pp'
|
6
|
-
|
7
6
|
gem 'libxml-ruby', '>= 0.8.3'
|
8
7
|
require 'xml'
|
9
8
|
require 'tempfile'
|
10
|
-
require '
|
11
|
-
require '
|
9
|
+
require 'simple_memoize'
|
10
|
+
require 'log4r'
|
12
11
|
|
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
|
37
|
-
# data in XML files. beware, it's not transactionally safe.
|
38
13
|
module DataMapper::Adapters
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
14
|
+
|
15
|
+
class XmlAdapterCache
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
#@@logger = Log4r::Logger.new 'cache'
|
19
|
+
#@@logger.outputters = Log4r::Outputter.stdout
|
20
|
+
@mtimes = Hash.new()
|
21
|
+
@classes = Hash.new()
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_mtime(file, mtime)
|
25
|
+
#@@logger.info("Saved mtime, #{file} -> #{mtime}")
|
46
26
|
@mtimes[file] = mtime
|
47
|
-
|
48
|
-
|
49
|
-
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete_mtime(file)
|
30
|
+
#@@logger.info("deleting the following mtime: #{file}")
|
50
31
|
@mtimes.delete(file)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_mtime(file)
|
35
|
+
return @mtimes[file]
|
36
|
+
end
|
37
|
+
|
38
|
+
def put(classname, id, object)
|
39
|
+
#@@logger.info("CACHE INSERT: #{classname} #{id} #{object.inspect}")
|
40
|
+
|
58
41
|
# check to see if we have a classname entry
|
59
42
|
if (@classes[classname] == nil)
|
60
43
|
@classes[classname] = Hash.new
|
61
44
|
end
|
62
|
-
|
45
|
+
|
63
46
|
hash = @classes[classname]
|
64
47
|
hash[id.to_s] = object
|
65
|
-
|
66
|
-
|
67
|
-
|
48
|
+
# @@logger.info("the hash is: #{hash.inspect}")
|
49
|
+
end
|
50
|
+
|
51
|
+
def delete(classname, id)
|
52
|
+
#@@logger.info("deleted the following from cache: #{classname} #{id.to_s}")
|
68
53
|
hash = @classes[classname]
|
54
|
+
#@@logger.info("the hash is: #{hash.inspect}")
|
69
55
|
unless hash == nil
|
70
56
|
hash.delete(id.to_s)
|
71
57
|
end
|
72
|
-
|
73
|
-
|
74
|
-
|
58
|
+
#@@logger.info("the hash is: #{hash.inspect}")
|
59
|
+
end
|
60
|
+
|
61
|
+
def get(classname, id)
|
62
|
+
#@@logger.info("CACHE FETCH: #{classname} #{id}")
|
63
|
+
#@@logger.info("Master classes: #{@classes.inspect}")
|
75
64
|
hash = @classes[classname]
|
76
|
-
|
77
|
-
|
78
|
-
|
65
|
+
#@@logger.info("the hash is: #{hash.inspect}")
|
66
|
+
object = hash[id]
|
67
|
+
#@@logger.info("The object is: #{object}")
|
68
|
+
return object
|
69
|
+
end
|
70
|
+
end
|
79
71
|
|
80
|
-
class XmlAdapter < AbstractAdapter
|
81
|
-
|
82
|
-
def loglevel=(loglevel)
|
83
|
-
@options[:loglevel] = loglevel
|
84
|
-
@logger.level = loglevel
|
85
|
-
end
|
86
|
-
|
87
|
-
def logger=(logger)
|
88
|
-
@options[:logger] = logger
|
89
|
-
@logger = logger
|
90
|
-
end
|
72
|
+
class XmlAdapter < AbstractAdapter
|
91
73
|
|
92
74
|
def initialize(name, options)
|
93
75
|
super
|
94
76
|
|
95
|
-
@options =
|
96
|
-
@options[:directory]
|
97
|
-
@options[:
|
98
|
-
|
99
|
-
@logger = @options[:logger]
|
100
|
-
@logger.level = @options[:loglevel]
|
101
|
-
@logger.debug('DM-XML-Adapter Initialized!')
|
77
|
+
@options = Hash.new
|
78
|
+
@options[:directory] = options[:directory]
|
79
|
+
@options[:directory] ||= './db'
|
80
|
+
|
102
81
|
@last_used_id = Hash.new
|
103
|
-
|
82
|
+
|
104
83
|
@cache = XmlAdapterCache.new
|
84
|
+
|
85
|
+
#@@logger = Log4r::Logger.new 'adapter'
|
86
|
+
#@@logger.outputters = Log4r::Outputter.stdout
|
105
87
|
|
106
88
|
end
|
107
|
-
|
108
|
-
def destroy_model_storage(model)
|
109
|
-
|
110
|
-
@logger.debug("Removing model storage for #{model}")
|
89
|
+
|
90
|
+
def destroy_model_storage(repository, model)
|
91
|
+
FileUtils.rm_rf(classname_to_dir(model.to_s))
|
111
92
|
end
|
112
|
-
|
113
|
-
def create_model_storage(model)
|
114
|
-
|
115
|
-
@logger.debug("Creating model storage for: #{model}")
|
93
|
+
|
94
|
+
def create_model_storage(repository, model)
|
95
|
+
FileUtils.mkdir_p(classname_to_dir(model.to_s))
|
116
96
|
end
|
117
|
-
|
118
|
-
def create(resources)
|
119
|
-
key = resources.first.model.key.first.name
|
97
|
+
|
98
|
+
def create(resources)
|
120
99
|
resources.each do |resource|
|
121
|
-
|
100
|
+
model = resource.model
|
101
|
+
id = find_free_id_for(resource.class.to_s)
|
122
102
|
# find name of key attribute
|
103
|
+
key = model.key.first.name
|
123
104
|
resource.attributes[key] = id
|
124
|
-
resource.instance_variable_set(
|
105
|
+
resource.instance_variable_set("@" + key.to_s, id)
|
125
106
|
save(resource)
|
126
|
-
end
|
107
|
+
end
|
108
|
+
return resources.size
|
127
109
|
end
|
128
|
-
|
110
|
+
|
129
111
|
def delete(collection)
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
@cache.delete_mtime(class_name_to_file(class_name, key))
|
140
|
-
end
|
141
|
-
return collection.size
|
112
|
+
collection.each do |result|
|
113
|
+
@last_used_id[result.class.to_s] = result.key.first
|
114
|
+
xml_destroy(result)
|
115
|
+
# also remove from cache
|
116
|
+
@cache.delete(result.model.to_s, result.key.first)
|
117
|
+
# also remove from mtimes
|
118
|
+
@cache.delete_mtime(class_name_to_file(result.model.to_s, result.key.first))
|
119
|
+
end
|
120
|
+
return collection.size
|
142
121
|
end
|
143
|
-
|
122
|
+
|
144
123
|
def update(attributes, collection)
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
end
|
124
|
+
# ok, for each object found we have to update the attribs we found
|
125
|
+
# first thing is figure out what class we are dealing with
|
126
|
+
# iterate over every object in this set and set the given attributes
|
127
|
+
collection.each do |obj|
|
128
|
+
attributes.each do |attrib|
|
129
|
+
# attrib is an array
|
130
|
+
# first member is Property object
|
131
|
+
# second member is the value
|
132
|
+
obj.instance_variable_set("@" + attrib[0].name.to_s, attrib[1])
|
133
|
+
end
|
134
|
+
save(obj)
|
135
|
+
end
|
158
136
|
return collection
|
159
137
|
end
|
160
|
-
|
138
|
+
|
161
139
|
def read(query)
|
162
|
-
|
140
|
+
return filter_result_set(get_all(query.model), query)
|
163
141
|
end
|
164
|
-
|
142
|
+
|
165
143
|
private
|
166
|
-
|
167
|
-
|
144
|
+
|
145
|
+
def xml_destroy(resource)
|
168
146
|
# take an objects class and ID and figure
|
169
147
|
# out what file it's in
|
170
148
|
# and then remove that file
|
171
|
-
|
149
|
+
class_name = resource.class.to_s
|
150
|
+
id = resource.key.first
|
151
|
+
file = class_name_to_file(class_name, id)
|
152
|
+
File.unlink(file)
|
172
153
|
end
|
173
|
-
|
154
|
+
|
174
155
|
def filter_result_set(objects, query)
|
156
|
+
#puts "before filter: #{objects.inspect}"
|
175
157
|
result_set = objects.clone
|
158
|
+
result_set = query.filter_records(result_set)
|
159
|
+
#puts "After filter: #{result_set.inspect}"
|
176
160
|
return query.filter_records(result_set)
|
177
161
|
end
|
178
|
-
|
162
|
+
|
179
163
|
def get_all(model)
|
180
|
-
|
181
|
-
|
182
|
-
directory = classname_to_dir(model_name)
|
164
|
+
#@@logger.info("Trying to get all: #{model.to_s}")
|
165
|
+
directory = classname_to_dir(model.to_s)
|
183
166
|
if ! File.exists?(directory)
|
167
|
+
#@@logger.error("The directory doesn't exist!")
|
184
168
|
return []
|
185
169
|
end
|
186
|
-
|
187
170
|
objects = []
|
188
|
-
Dir
|
171
|
+
Dir.entries(directory).select {|f| f.match(/\.xml$/) }.each do |filename|
|
172
|
+
filename = directory + "/" + filename
|
189
173
|
# see if we have a nice cached version
|
190
|
-
|
191
|
-
|
192
|
-
|
174
|
+
mtime = File.mtime(filename)
|
175
|
+
cache_mtime = @cache.get_mtime(filename)
|
176
|
+
#puts "file mtime: #{mtime} cache mtime: #{@cache.get_mtime(filename)}"
|
177
|
+
if (mtime != nil and cache_mtime != nil)
|
178
|
+
#puts "comparing! #{mtime < cache_mtime}"
|
179
|
+
end
|
180
|
+
if (mtime != nil and cache_mtime != nil and mtime == cache_mtime)
|
181
|
+
# we hav ea nice cached object..
|
182
|
+
objects << @cache.get(model.to_s, file_to_id(filename))
|
193
183
|
else
|
194
|
-
|
184
|
+
#@@logger.info("CACHE MISS")
|
185
|
+
# the file's newer, so we gotta load it up
|
195
186
|
object = file_to_object(filename, model)
|
196
187
|
objects << object
|
197
|
-
|
198
|
-
next if (key == nil)
|
199
|
-
key = object.key.first
|
200
|
-
@cache.put(model_name, key, object)
|
188
|
+
@cache.put(model.to_s, object.key.first, object)
|
201
189
|
@cache.set_mtime(filename, File.mtime(filename))
|
202
190
|
end
|
203
191
|
end
|
204
192
|
return objects
|
205
193
|
end
|
206
|
-
|
207
|
-
def has_cached_version?(filename)
|
208
|
-
mtime = File.mtime(filename)
|
209
|
-
cache_mtime = @cache.get_mtime(filename)
|
210
|
-
return true if (mtime != nil and cache_mtime != nil and mtime == cache_mtime)
|
211
|
-
end
|
212
|
-
|
194
|
+
|
213
195
|
def file_to_id(file)
|
214
196
|
return file.match(/([0-9]+)\.xml/)[1]
|
215
197
|
end
|
216
|
-
|
198
|
+
|
199
|
+
def is_integer?(number)
|
200
|
+
if number.class == String and number.match(/^\-*[0-9]+$/)
|
201
|
+
return true
|
202
|
+
end
|
203
|
+
return false
|
204
|
+
end
|
205
|
+
|
217
206
|
def file_to_object(file, model)
|
218
|
-
|
207
|
+
|
219
208
|
# allocate new object to receive these fields
|
220
|
-
if (
|
221
|
-
|
209
|
+
if (model.to_s.match(/\:\:/))
|
210
|
+
modname, clazz = model.to_s.split("::")
|
211
|
+
new_obj = Kernel.const_get(modname).const_get(clazz).new
|
222
212
|
else
|
223
|
-
|
213
|
+
clazz = model.to_s
|
214
|
+
new_obj = Kernel.const_get(clazz).new
|
224
215
|
end
|
225
|
-
|
216
|
+
|
217
|
+
# file is our XML file
|
218
|
+
string = IO.read(file)
|
219
|
+
parser = XML::Parser.string(string)
|
220
|
+
doc = parser.parse
|
221
|
+
root_node = doc.root
|
226
222
|
# iterate over children
|
227
|
-
|
228
|
-
child_class = child.attributes[
|
223
|
+
root_node.children.each do |child|
|
224
|
+
child_class = child.attributes["class"]
|
229
225
|
if child_class != nil
|
230
226
|
# this means we have an attribute
|
231
|
-
|
227
|
+
if (child_class == "Integer")
|
228
|
+
new_obj.instance_variable_set("@#{child.name}", child.content.to_i)
|
229
|
+
elsif (child_class == "String")
|
230
|
+
new_obj.instance_variable_set("@#{child.name}", child.content)
|
231
|
+
elsif (child_class == "TrueClass")
|
232
|
+
new_obj.instance_variable_set("@#{child.name}", true)
|
233
|
+
elsif (child_class == "FalseClass")
|
234
|
+
new_obj.instance_variable_set("@#{child.name}", false)
|
235
|
+
elsif (child_class == "BigDecimal")
|
236
|
+
new_obj.instance_variable_set("@#{child.name}", BigDecimal.new(child.content))
|
237
|
+
elsif (child_class == "DateTime")
|
238
|
+
new_obj.instance_variable_set("@#{child.name}", DateTime.parse(child.content))
|
239
|
+
end
|
232
240
|
end
|
233
241
|
end
|
234
|
-
|
242
|
+
|
235
243
|
return new_obj
|
236
244
|
end
|
237
|
-
|
238
|
-
|
239
|
-
if (child_class == 'String')
|
240
|
-
new_obj.instance_variable_set("@#{child.name}", child.content)
|
241
|
-
elsif (child_class == 'Integer')
|
242
|
-
new_obj.instance_variable_set("@#{child.name}", child.content.to_i)
|
243
|
-
elsif (child_class == 'TrueClass')
|
244
|
-
new_obj.instance_variable_set("@#{child.name}", true)
|
245
|
-
elsif (child_class == 'FalseClass')
|
246
|
-
new_obj.instance_variable_set("@#{child.name}", false)
|
247
|
-
elsif (child_class == 'BigDecimal')
|
248
|
-
new_obj.instance_variable_set("@#{child.name}", BigDecimal.new(child.content))
|
249
|
-
elsif (child_class == 'DateTime')
|
250
|
-
new_obj.instance_variable_set("@#{child.name}", DateTime.parse(child.content))
|
251
|
-
elsif (child_class == 'Date')
|
252
|
-
new_obj.instance_variable_set("@#{child.name}", Date.parse(child.content))
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
def find_free_id_for(class_name)
|
245
|
+
|
246
|
+
def find_free_id_for(class_name)
|
257
247
|
# if there are no entries in the directory
|
258
248
|
# or the directory doesn't exist
|
259
249
|
# we need to create it...
|
260
250
|
if ! File.exists?(classname_to_dir(class_name))
|
261
251
|
# default ID
|
262
|
-
return
|
252
|
+
return 0
|
263
253
|
end
|
264
254
|
directory = Dir.new(classname_to_dir(class_name))
|
265
255
|
if directory.entries.size == 0
|
266
|
-
return
|
256
|
+
return 0
|
267
257
|
end
|
268
|
-
id = @last_used_id[class_name] ||
|
258
|
+
id = @last_used_id[class_name] || 0
|
269
259
|
while true do
|
270
|
-
|
271
|
-
if ! File.exists?(filename)
|
260
|
+
if ! File.exists?(File.join(directory.path, id.to_s + ".xml"))
|
272
261
|
@last_used_id[class_name] = id
|
273
262
|
return id
|
274
263
|
end
|
275
264
|
id += 1
|
276
265
|
end
|
277
266
|
end
|
278
|
-
|
267
|
+
|
279
268
|
def save(resource)
|
269
|
+
|
280
270
|
# since we're saving, purge the cache
|
281
|
-
|
282
|
-
|
283
|
-
@cache.delete(resource_class, resource_key)
|
284
|
-
@cache.delete_mtime(class_name_to_file(resource_class, resource_key))
|
271
|
+
@cache.delete(resource.class.to_s, resource.key.first)
|
272
|
+
@cache.delete_mtime(class_name_to_file(resource.class.to_s, resource.key.first))
|
285
273
|
|
274
|
+
# file = File.join(class_name_to_file(resource.class.to_s, resource.key.first))
|
286
275
|
# see if the directory exists, if it doesn't, we need to create it
|
287
|
-
if ! File.exists?(classname_to_dir(
|
288
|
-
FileUtils.mkdir_p(classname_to_dir(
|
276
|
+
if ! File.exists?(classname_to_dir(resource.class.to_s))
|
277
|
+
FileUtils.mkdir_p(classname_to_dir(resource.class.to_s))
|
289
278
|
end
|
290
279
|
|
280
|
+
# puts resource.model.properties.inspect
|
281
|
+
|
291
282
|
# set up builder
|
292
|
-
out_string =
|
283
|
+
out_string = ""
|
293
284
|
xml = Builder::XmlMarkup.new(:target => out_string, :indent => 1)
|
294
|
-
|
285
|
+
|
295
286
|
# iterate over the resource and figure out the fields
|
296
|
-
|
287
|
+
# class_name = resource.model.to_s.gsub(/\:/, "_")
|
288
|
+
xml.tag!("RubyObject", :class => resource.model.to_s) do
|
297
289
|
resource.model.properties.each do |property|
|
298
|
-
|
299
|
-
|
290
|
+
#puts "saving prop: #{property.name}"
|
291
|
+
#puts "primitive: #{property.primitive}"
|
292
|
+
value = resource.instance_variable_get("@" + property.name.to_s)
|
300
293
|
# special case for false
|
301
294
|
if property.primitive == TrueClass and value == false
|
302
|
-
|
303
|
-
elsif (property.primitive == BigDecimal
|
304
|
-
|
295
|
+
xml.tag!(property.name.to_s, false, :class => FalseClass.to_s)
|
296
|
+
elsif (value != nil and property.primitive == BigDecimal)
|
297
|
+
xml.tag!(property.name.to_s, value.to_s("F"), :class => BigDecimal)
|
305
298
|
elsif (value != nil)
|
306
|
-
|
299
|
+
xml.tag!(property.name.to_s, value, :class => property.primitive)
|
307
300
|
end
|
308
301
|
end
|
309
302
|
end
|
310
|
-
|
311
|
-
xmlfile = File.new(class_name_to_file(
|
312
|
-
tempfile = Tempfile.new(
|
303
|
+
|
304
|
+
xmlfile = File.new(class_name_to_file(resource.class.to_s, resource.key.first), "w")
|
305
|
+
tempfile = Tempfile.new("dm-xml-adapter", "/tmp")
|
313
306
|
tempfile.puts out_string
|
314
307
|
tempfile.close
|
315
308
|
FileUtils.mv(tempfile.path,xmlfile.path)
|
316
|
-
@logger.debug("Saved to: #{xmlfile.path}")
|
317
309
|
return xmlfile
|
318
|
-
|
310
|
+
|
319
311
|
end
|
320
312
|
|
321
313
|
def classname_to_dir(class_name)
|
322
314
|
return File.join(@options[:directory],
|
323
|
-
|
315
|
+
class_name.gsub("/", "_").gsub(":", "_"))
|
324
316
|
end
|
325
|
-
|
317
|
+
|
326
318
|
def class_name_to_file(class_name, id)
|
327
|
-
return File.join(classname_to_dir(class_name), id.to_s +
|
319
|
+
return File.join(classname_to_dir(class_name), id.to_s + ".xml")
|
328
320
|
end
|
329
321
|
|
322
|
+
memoize(:file_to_id)
|
323
|
+
memoize(:classname_to_dir)
|
324
|
+
memoize(:class_name_to_file)
|
325
|
+
|
330
326
|
end
|
331
327
|
end
|
332
328
|
|
data/spec/dm-xml-adapter_spec.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'dm-core'
|
3
3
|
require 'pathname'
|
4
|
-
require 'dm-migrations'
|
5
4
|
require Pathname(__FILE__).dirname.expand_path + 'spec_helper'
|
6
5
|
|
7
6
|
describe DataMapper::Adapters::XmlAdapter do
|
8
7
|
before(:each) do
|
9
8
|
@adapter = DataMapper.setup(:default, {:adapter => 'xml', :directory => 'db'})
|
10
|
-
DataMapper.auto_migrate!
|
11
9
|
delete_all
|
12
10
|
end
|
13
11
|
|
@@ -15,14 +13,14 @@ describe DataMapper::Adapters::XmlAdapter do
|
|
15
13
|
XMLTest::User.all.each {|u| u.destroy }
|
16
14
|
XMLTest::Post.all.each {|p| p.destroy }
|
17
15
|
AutoQuote.all.each {|aq| aq.destroy }
|
18
|
-
|
19
|
-
|
20
|
-
Three::Level::Test::IsFun.all.each {|d| d.destroy }
|
16
|
+
Food.all.each {|f| f.destroy }
|
17
|
+
Drink.all.each {|d| d.destroy }
|
21
18
|
end
|
22
|
-
|
19
|
+
|
23
20
|
after(:each) do
|
24
21
|
delete_all
|
25
22
|
end
|
23
|
+
|
26
24
|
|
27
25
|
describe "CRUD" do
|
28
26
|
|
@@ -32,14 +30,14 @@ describe DataMapper::Adapters::XmlAdapter do
|
|
32
30
|
AutoQuote.all.size.should == 1
|
33
31
|
end
|
34
32
|
end
|
35
|
-
|
33
|
+
|
36
34
|
describe "content attribute" do
|
37
35
|
it "should be able to handle a content attribute" do
|
38
36
|
XMLTest::User.create(:name => "contentking", :content => "cool")
|
39
37
|
XMLTest::User.all.size.should == 1
|
40
38
|
end
|
41
39
|
end
|
42
|
-
|
40
|
+
|
43
41
|
describe "datetime" do
|
44
42
|
it "should do datetime" do
|
45
43
|
u1 = XMLTest::User.new
|
@@ -51,17 +49,6 @@ describe DataMapper::Adapters::XmlAdapter do
|
|
51
49
|
end
|
52
50
|
end
|
53
51
|
|
54
|
-
describe "date" do
|
55
|
-
it "should do date" do
|
56
|
-
u1 = XMLTest::User.new
|
57
|
-
u1.name = "cool!"
|
58
|
-
u1.date = Date.parse("01/01/2001")
|
59
|
-
u1.save
|
60
|
-
u2 = XMLTest::User.first(:name => "cool!")
|
61
|
-
u2.date.class.should == Date
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
52
|
describe "boolean" do
|
66
53
|
it "should be boolean" do
|
67
54
|
u1 = XMLTest::User.new
|
@@ -80,7 +67,7 @@ describe DataMapper::Adapters::XmlAdapter do
|
|
80
67
|
u2.cool.class.should == FalseClass
|
81
68
|
end
|
82
69
|
end
|
83
|
-
|
70
|
+
|
84
71
|
describe "associations" do
|
85
72
|
it "should have associations" do
|
86
73
|
u1 = XMLTest::User.new
|
@@ -99,14 +86,14 @@ describe DataMapper::Adapters::XmlAdapter do
|
|
99
86
|
u3.posts.size.should == 2
|
100
87
|
end
|
101
88
|
end
|
102
|
-
|
89
|
+
|
103
90
|
describe "get all" do
|
104
91
|
it "should get all" do
|
105
92
|
XMLTest::User.create(:name => :yeah)
|
106
93
|
XMLTest::User.all.should_not == nil
|
107
94
|
end
|
108
95
|
end
|
109
|
-
|
96
|
+
|
110
97
|
describe "update" do
|
111
98
|
it "should update" do
|
112
99
|
u1 = XMLTest::User.new
|
@@ -125,7 +112,7 @@ describe DataMapper::Adapters::XmlAdapter do
|
|
125
112
|
u.user_id.should_not == nil
|
126
113
|
end
|
127
114
|
end
|
128
|
-
|
115
|
+
|
129
116
|
describe "delete" do
|
130
117
|
it "should delete someone" do
|
131
118
|
user = XMLTest::User.create
|
@@ -141,7 +128,7 @@ describe DataMapper::Adapters::XmlAdapter do
|
|
141
128
|
user1.money.class.should == BigDecimal
|
142
129
|
end
|
143
130
|
end
|
144
|
-
|
131
|
+
|
145
132
|
describe "find not" do
|
146
133
|
it "should find someone with a not clause" do
|
147
134
|
user1 = XMLTest::User.create(:name => "joe")
|
@@ -156,37 +143,15 @@ describe DataMapper::Adapters::XmlAdapter do
|
|
156
143
|
100.times {|n| Drink.create(:name => "Drink#{n}") }
|
157
144
|
# pick a random one
|
158
145
|
ids = Drink.all.map {|d| d.drink_id }
|
159
|
-
|
160
|
-
drink = Drink.get(random_key)
|
146
|
+
drink = Drink.get(ids[rand(100).to_i])
|
161
147
|
drink.name = "Drinky drink!"
|
162
148
|
drink.save
|
163
149
|
Drink.first(:name => "Drinky drink!").should_not == nil
|
164
150
|
end
|
165
151
|
end
|
166
|
-
|
167
|
-
describe "complex class name" do
|
168
|
-
it "should be able to persist" do
|
169
|
-
fun = Three::Level::Test::IsFun.new
|
170
|
-
fun.superfun = true
|
171
|
-
fun.save
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
describe "logging support" do
|
176
|
-
it "should work with logging" do
|
177
|
-
@adapter.loglevel = Logger::DEBUG
|
178
|
-
@adapter.logger = Logger.new("/dev/null")
|
179
|
-
XMLTest::User.create(:name => "contentking", :content => "cool")
|
180
|
-
XMLTest::User.all.size.should == 1
|
181
|
-
DataMapper.repository.adapter.loglevel = Logger::DEBUG
|
182
|
-
DataMapper.repository.adapter.logger = Logger.new('/dev/null')
|
183
|
-
XMLTest::User.create(:name => "contentking", :content => "cool")
|
184
|
-
XMLTest::User.all.size.should == 2
|
185
|
-
end
|
186
|
-
|
187
|
-
end
|
188
|
-
|
152
|
+
|
189
153
|
end
|
154
|
+
|
190
155
|
|
191
156
|
end
|
192
157
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,64 +1,51 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'dm-core'
|
3
3
|
require 'pathname'
|
4
|
-
require '
|
4
|
+
require Pathname(__FILE__).dirname.parent.expand_path + 'lib/dm-xml-adapter'
|
5
5
|
|
6
6
|
class Food
|
7
|
-
|
7
|
+
include DataMapper::Resource
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
property :food_id, Serial
|
10
|
+
property :name, String
|
11
11
|
end
|
12
12
|
|
13
13
|
class Drink
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
include DataMapper::Resource
|
15
|
+
|
16
|
+
property :drink_id, Serial
|
17
|
+
property :name, String
|
18
18
|
end
|
19
19
|
|
20
20
|
class AutoQuote
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
include DataMapper::Resource
|
22
|
+
|
23
|
+
property :quote_id, Serial
|
24
|
+
property :fullname, String
|
25
25
|
end
|
26
26
|
|
27
27
|
module XMLTest
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
has n, :posts, :model => "Post"
|
51
|
-
end
|
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, BigDecimal
|
45
|
+
property :created, DateTime
|
46
|
+
property :cool, Boolean
|
47
|
+
property :content, String
|
48
|
+
|
49
|
+
has n, :posts, :model => "Post"
|
52
50
|
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
|
64
51
|
end
|
metadata
CHANGED
@@ -1,155 +1,89 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-xml-adapter
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.571"
|
6
5
|
platform: ruby
|
7
|
-
authors:
|
6
|
+
authors:
|
8
7
|
- Joshua Harding
|
9
8
|
autorequire: dm-xml-adapter
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
|
12
|
+
date: 2010-02-09 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
15
16
|
name: libxml-ruby
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>='
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '0'
|
22
17
|
type: :runtime
|
23
|
-
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
- !ruby/object:Gem::Dependency
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
31
26
|
name: builder
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ! '>='
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: '0'
|
38
27
|
type: :runtime
|
39
|
-
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
|
-
requirements:
|
51
|
-
- - ! '>='
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: simple_memoize
|
54
37
|
type: :runtime
|
55
|
-
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: dm-migrations
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ! '>='
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '0'
|
70
|
-
type: :runtime
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ! '>='
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '0'
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: rspec
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ! '>='
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '0'
|
86
|
-
type: :runtime
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0'
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: lrucache
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
|
-
requirements:
|
99
|
-
- - ! '>='
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: '0'
|
102
|
-
type: :runtime
|
103
|
-
prerelease: false
|
104
|
-
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ! '>='
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '0'
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
110
45
|
description:
|
111
46
|
email: josh@statewidesoftware.com
|
112
47
|
executables: []
|
48
|
+
|
113
49
|
extensions: []
|
114
|
-
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
115
52
|
- README
|
116
|
-
files:
|
53
|
+
files:
|
117
54
|
- lib/dm-xml-adapter.rb
|
118
55
|
- lib/ratecounter.rb
|
119
56
|
- spec/dm-xml-adapter_spec.rb
|
120
57
|
- spec/spec_helper.rb
|
121
58
|
- README
|
59
|
+
has_rdoc: true
|
122
60
|
homepage:
|
123
61
|
licenses: []
|
62
|
+
|
124
63
|
post_install_message:
|
125
64
|
rdoc_options: []
|
126
|
-
|
65
|
+
|
66
|
+
require_paths:
|
127
67
|
- lib
|
128
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
- - ! '>='
|
141
|
-
- !ruby/object:Gem::Version
|
142
|
-
version: '0'
|
143
|
-
segments:
|
144
|
-
- 0
|
145
|
-
hash: 758938256756139992
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: "0"
|
73
|
+
version:
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
version:
|
146
80
|
requirements: []
|
81
|
+
|
147
82
|
rubyforge_project:
|
148
|
-
rubygems_version: 1.
|
83
|
+
rubygems_version: 1.3.5
|
149
84
|
signing_key:
|
150
85
|
specification_version: 3
|
151
|
-
summary: a XML adapter for DataMapper. this adapter allows you to use DataMapper with
|
152
|
-
|
153
|
-
test_files:
|
86
|
+
summary: a XML adapter for DataMapper. this adapter allows you to use DataMapper with XML files as a backing store.
|
87
|
+
test_files:
|
154
88
|
- spec/dm-xml-adapter_spec.rb
|
155
89
|
- spec/spec_helper.rb
|