dm-yaml-adapter 0.5
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 +49 -0
- data/lib/dm-yaml-adapter.rb +189 -0
- data/spec/dm-yaml-adapter_spec.rb +53 -0
- data/spec/spec_helper.rb +23 -0
- metadata +57 -0
data/README
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
dm-yaml-adapter
|
2
|
+
|
3
|
+
This adapter is for DataMapper. This allows you to persist objects to YAML files and still have the query capabilities of DataMapper. I wouldn't scale this out to a zillion files, but if you have a lot of read action on a small database this could be the project for you. OR use it to better understand DataMapper.
|
4
|
+
|
5
|
+
|
6
|
+
Example usage:
|
7
|
+
|
8
|
+
We have to tell datamapper where we will be storing the YAML files.
|
9
|
+
directory tells the adapter where to store.
|
10
|
+
|
11
|
+
DataMapper.setup(:default, {:adapter => 'yaml', :directory => 'db'})
|
12
|
+
|
13
|
+
|
14
|
+
Trying it out:
|
15
|
+
|
16
|
+
If you want some examples of defining classes, check out the spec directory.
|
17
|
+
|
18
|
+
Anyway, assuming you have a decent environment set up, you can try out some examples.
|
19
|
+
|
20
|
+
If you want to use irb to try some of this interactively, try 'irb' and then
|
21
|
+
> load 'irbhelper.irb'
|
22
|
+
|
23
|
+
That sets up a basic environment with User and Post resources already defined.
|
24
|
+
|
25
|
+
irb(main):001:0> load 'irbhelper.irb'
|
26
|
+
=> true
|
27
|
+
irb(main):002:0> u = User.create(:name => 'Bob', :age => 55)
|
28
|
+
=> #<User user_id=1 name="Bob" age=55>
|
29
|
+
irb(main):003:0> u.save
|
30
|
+
=> true
|
31
|
+
irb(main):004:0> User.all
|
32
|
+
=> [#<User user_id=1 name="Bob" age=55>]
|
33
|
+
irb(main):005:0>
|
34
|
+
|
35
|
+
If you use another window to check out the db directory you should have a nice User directory with a 1.yaml file in there, with the data of Bob.
|
36
|
+
|
37
|
+
You can also add another object and start playing around with some queries.
|
38
|
+
|
39
|
+
irb(main):005:0> User.create(:name => 'Sue', :age => 32)
|
40
|
+
=> #<User user_id=2 name="Sue" age=32>
|
41
|
+
irb(main):006:0> User.all(:age => 32)
|
42
|
+
=> [#<User user_id=2 name="Sue" age=32>]
|
43
|
+
irb(main):007:0> User.all
|
44
|
+
=> [#<User user_id=1 name="Bob" age=55>, #<User user_id=2 name="Sue" age=32>]
|
45
|
+
irb(main):008:0> u.destroy
|
46
|
+
=> true
|
47
|
+
irb(main):009:0> User.all
|
48
|
+
=> [#<User user_id=2 name="Sue" age=32>]
|
49
|
+
irb(main):010:0>
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'dm-core'
|
3
|
+
require 'yaml'
|
4
|
+
require 'dm-core/adapters/abstract_adapter'
|
5
|
+
|
6
|
+
module DataMapper::Adapters
|
7
|
+
|
8
|
+
class YamlAdapter < AbstractAdapter
|
9
|
+
|
10
|
+
def initialize(name, options)
|
11
|
+
super
|
12
|
+
|
13
|
+
@options = Hash.new
|
14
|
+
|
15
|
+
@options[:directory] = options[:directory]
|
16
|
+
|
17
|
+
@options[:directory] ||= './db'
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def destroy_model_storage(repository, model)
|
22
|
+
FileUtils.rm_rf(classname_to_dir(model.to_s))
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_model_storage(repository, model)
|
26
|
+
FileUtils.mkdir_p(classname_to_dir(model.to_s))
|
27
|
+
end
|
28
|
+
|
29
|
+
def create(resources)
|
30
|
+
resources.each do |resource|
|
31
|
+
model = resource.model
|
32
|
+
id = find_free_id_for(resource.class.to_s)
|
33
|
+
# find name of key attribute
|
34
|
+
key = model.key.first.name
|
35
|
+
resource.attributes[key] = id
|
36
|
+
resource.instance_variable_set("@" + key.to_s, id)
|
37
|
+
save(resource)
|
38
|
+
end
|
39
|
+
return resources.size
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete(query)
|
43
|
+
resultset = yaml_query(query)
|
44
|
+
resultset.each do |result|
|
45
|
+
yaml_destroy(result)
|
46
|
+
end
|
47
|
+
return resultset.size
|
48
|
+
end
|
49
|
+
|
50
|
+
def read_one(query)
|
51
|
+
return(filter_result_set(get_all(query.model), query).first)
|
52
|
+
end
|
53
|
+
|
54
|
+
def update(attributes, query)
|
55
|
+
# ok, for each object found we have to update the attribs we found
|
56
|
+
# first thing is figure out what class we are dealing with
|
57
|
+
clazz = query.model
|
58
|
+
# next, get all the matching objects
|
59
|
+
objs = filter_result_set(clazz.all, query)
|
60
|
+
# iterate over every object in this set and set the given attributes
|
61
|
+
objs.each do |obj|
|
62
|
+
attributes.each do |attrib|
|
63
|
+
# attrib is an array
|
64
|
+
# first member is Property object
|
65
|
+
# second member is the value
|
66
|
+
obj.instance_variable_set("@" + attrib[0].name.to_s, attrib[1])
|
67
|
+
end
|
68
|
+
save(obj)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def read_many(query)
|
73
|
+
return filter_result_set(get_all(query.model), query)
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def yaml_destroy(resource)
|
80
|
+
# take an objects class and ID and figure
|
81
|
+
# out what file it's in
|
82
|
+
# and then remove that file
|
83
|
+
class_name = resource.class.to_s
|
84
|
+
id = resource.key.first
|
85
|
+
file = class_name_to_file(class_name, id)
|
86
|
+
File.unlink(file)
|
87
|
+
end
|
88
|
+
|
89
|
+
def yaml_query(query)
|
90
|
+
# in this method, we want to take each condition and figure out
|
91
|
+
# what we should return
|
92
|
+
|
93
|
+
# first is figuring out our class
|
94
|
+
model = query.model
|
95
|
+
# if we just want all the objects...
|
96
|
+
if (query.conditions.empty?)
|
97
|
+
return get_all(model)
|
98
|
+
end
|
99
|
+
|
100
|
+
# otherwise we have to filter on some conditions...
|
101
|
+
all_objs = get_all(model)
|
102
|
+
# for each object, check all the conditions
|
103
|
+
filter_result_set(all_objs, query)
|
104
|
+
end
|
105
|
+
|
106
|
+
def filter_result_set(objects, query)
|
107
|
+
result_set = objects.clone
|
108
|
+
objects.each do |obj|
|
109
|
+
query.conditions.each do |operator, property, value|
|
110
|
+
case operator
|
111
|
+
# handle eql
|
112
|
+
when :eql, :like
|
113
|
+
if ! (obj.instance_variable_get("@" + property.field) == value)
|
114
|
+
# remove from teh result set...
|
115
|
+
result_set.delete(obj)
|
116
|
+
end
|
117
|
+
# handle :not
|
118
|
+
when :not
|
119
|
+
if (obj.instance_variable_get("@" + property.field) == value)
|
120
|
+
result_set.delete(obj)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
return result_set
|
126
|
+
end
|
127
|
+
|
128
|
+
def get_all(clazz)
|
129
|
+
objects = Array.new
|
130
|
+
directory = classname_to_dir(clazz.to_s)
|
131
|
+
if ! File.exists?(directory)
|
132
|
+
return objects
|
133
|
+
end
|
134
|
+
Dir.entries(directory).grep(/\.yaml$/).each do |entry|
|
135
|
+
objects << file_to_object(File.join(directory, entry))
|
136
|
+
end
|
137
|
+
return objects
|
138
|
+
end
|
139
|
+
|
140
|
+
def file_to_object(file)
|
141
|
+
new_obj = YAML.load_file(file)
|
142
|
+
new_obj.instance_variable_set("@new_record", false)
|
143
|
+
return new_obj
|
144
|
+
end
|
145
|
+
|
146
|
+
def find_free_id_for(class_name)
|
147
|
+
# if there are no entries in the directory, or the directory doesn't exist
|
148
|
+
# we need to create it...
|
149
|
+
|
150
|
+
if ! File.exists?(classname_to_dir(class_name))
|
151
|
+
# default ID
|
152
|
+
return 1
|
153
|
+
end
|
154
|
+
directory = classname_to_dir(class_name)
|
155
|
+
if directory.entries.size == 0
|
156
|
+
return 1
|
157
|
+
end
|
158
|
+
free_id = -1
|
159
|
+
id = 1
|
160
|
+
until free_id != -1 do
|
161
|
+
id += 1
|
162
|
+
if ! File.exists?(File.join(directory, id.to_s + ".yaml"))
|
163
|
+
return id
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def save(resource)
|
169
|
+
file = File.join(class_name_to_file(resource.class.to_s, resource.id))
|
170
|
+
# see if the directory exists, if it doesn't, we need to create it
|
171
|
+
if ! File.exists?(classname_to_dir(resource.class.to_s))
|
172
|
+
FileUtils.mkdir_p(classname_to_dir(resource.class.to_s))
|
173
|
+
end
|
174
|
+
yamlfile = File.new(class_name_to_file(resource.class.to_s, resource.id), "w")
|
175
|
+
yamlfile.puts resource.to_yaml
|
176
|
+
yamlfile.close
|
177
|
+
end
|
178
|
+
|
179
|
+
def classname_to_dir(class_name)
|
180
|
+
return File.join(@options[:directory], class_name.gsub("/", "_"))
|
181
|
+
end
|
182
|
+
|
183
|
+
def class_name_to_file(class_name, id)
|
184
|
+
return File.join(classname_to_dir(class_name), id.to_s + ".yaml")
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'dm-core'
|
3
|
+
require 'dm-yaml-adapter'
|
4
|
+
require 'pathname'
|
5
|
+
require Pathname(__FILE__).dirname.expand_path + 'spec_helper'
|
6
|
+
|
7
|
+
describe DataMapper::Adapters::YamlAdapter do
|
8
|
+
before(:all) do
|
9
|
+
@adapter = DataMapper.setup(:default, {:adapter => 'yaml', :directory => 'db'})
|
10
|
+
User.auto_migrate!
|
11
|
+
@user1 = User.create(:name => 'tom')
|
12
|
+
@user2 = User.create(:name => 'jim')
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "CRUD" do
|
16
|
+
|
17
|
+
describe "create" do
|
18
|
+
it "should create" do
|
19
|
+
@user1.user_id.should_not == nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "read" do
|
24
|
+
it "should read all" do
|
25
|
+
begin
|
26
|
+
users = User.all
|
27
|
+
rescue Exception => e
|
28
|
+
puts e
|
29
|
+
puts e.backtrace
|
30
|
+
end
|
31
|
+
users.size.should_not == 0
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "delete" do
|
36
|
+
it "should delete someone" do
|
37
|
+
user = User.create
|
38
|
+
user.destroy.should == true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "find not" do
|
43
|
+
it "should find someone with a not clause" do
|
44
|
+
users = User.all(:user_id.not => @user1.id)
|
45
|
+
users.first.user_id.should_not == @user1.id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
end
|
53
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'dm-core'
|
3
|
+
require 'pathname'
|
4
|
+
require Pathname(__FILE__).dirname.parent.expand_path + 'lib/dm-yaml-adapter'
|
5
|
+
|
6
|
+
class Post
|
7
|
+
include DataMapper::Resource
|
8
|
+
|
9
|
+
property :post_id, Serial
|
10
|
+
property :title, String
|
11
|
+
|
12
|
+
belongs_to :user
|
13
|
+
end
|
14
|
+
|
15
|
+
class User
|
16
|
+
include DataMapper::Resource
|
17
|
+
|
18
|
+
property :user_id, Serial
|
19
|
+
property :name, String
|
20
|
+
property :age, Integer
|
21
|
+
|
22
|
+
has n, :posts
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dm-yaml-adapter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.5"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joshua Harding
|
8
|
+
autorequire: dm-yaml-adapter
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-05-20 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: josh@statewidesoftware.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
files:
|
25
|
+
- lib/dm-yaml-adapter.rb
|
26
|
+
- spec/dm-yaml-adapter_spec.rb
|
27
|
+
- spec/spec_helper.rb
|
28
|
+
- README
|
29
|
+
has_rdoc: true
|
30
|
+
homepage:
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: "0"
|
41
|
+
version:
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
version:
|
48
|
+
requirements: []
|
49
|
+
|
50
|
+
rubyforge_project:
|
51
|
+
rubygems_version: 1.3.1
|
52
|
+
signing_key:
|
53
|
+
specification_version: 2
|
54
|
+
summary: a YAML adapter for DataMapper. this (slow) adapter allows you to use DataMapper with YAML files as a backing store.
|
55
|
+
test_files:
|
56
|
+
- spec/dm-yaml-adapter_spec.rb
|
57
|
+
- spec/spec_helper.rb
|