dm-core 0.9.2
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/CHANGELOG +144 -0
- data/FAQ +74 -0
- data/MIT-LICENSE +22 -0
- data/QUICKLINKS +12 -0
- data/README +143 -0
- data/lib/dm-core.rb +213 -0
- data/lib/dm-core/adapters.rb +4 -0
- data/lib/dm-core/adapters/abstract_adapter.rb +202 -0
- data/lib/dm-core/adapters/data_objects_adapter.rb +701 -0
- data/lib/dm-core/adapters/mysql_adapter.rb +132 -0
- data/lib/dm-core/adapters/postgres_adapter.rb +179 -0
- data/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
- data/lib/dm-core/associations.rb +172 -0
- data/lib/dm-core/associations/many_to_many.rb +138 -0
- data/lib/dm-core/associations/many_to_one.rb +101 -0
- data/lib/dm-core/associations/one_to_many.rb +275 -0
- data/lib/dm-core/associations/one_to_one.rb +61 -0
- data/lib/dm-core/associations/relationship.rb +116 -0
- data/lib/dm-core/associations/relationship_chain.rb +74 -0
- data/lib/dm-core/auto_migrations.rb +64 -0
- data/lib/dm-core/collection.rb +604 -0
- data/lib/dm-core/hook.rb +11 -0
- data/lib/dm-core/identity_map.rb +45 -0
- data/lib/dm-core/is.rb +16 -0
- data/lib/dm-core/logger.rb +233 -0
- data/lib/dm-core/migrations/destructive_migrations.rb +17 -0
- data/lib/dm-core/migrator.rb +29 -0
- data/lib/dm-core/model.rb +399 -0
- data/lib/dm-core/naming_conventions.rb +52 -0
- data/lib/dm-core/property.rb +611 -0
- data/lib/dm-core/property_set.rb +158 -0
- data/lib/dm-core/query.rb +590 -0
- data/lib/dm-core/repository.rb +159 -0
- data/lib/dm-core/resource.rb +618 -0
- data/lib/dm-core/scope.rb +35 -0
- data/lib/dm-core/support.rb +7 -0
- data/lib/dm-core/support/array.rb +13 -0
- data/lib/dm-core/support/assertions.rb +8 -0
- data/lib/dm-core/support/errors.rb +23 -0
- data/lib/dm-core/support/kernel.rb +7 -0
- data/lib/dm-core/support/symbol.rb +41 -0
- data/lib/dm-core/transaction.rb +267 -0
- data/lib/dm-core/type.rb +160 -0
- data/lib/dm-core/type_map.rb +80 -0
- data/lib/dm-core/types.rb +19 -0
- data/lib/dm-core/types/boolean.rb +7 -0
- data/lib/dm-core/types/discriminator.rb +32 -0
- data/lib/dm-core/types/object.rb +20 -0
- data/lib/dm-core/types/paranoid_boolean.rb +23 -0
- data/lib/dm-core/types/paranoid_datetime.rb +22 -0
- data/lib/dm-core/types/serial.rb +9 -0
- data/lib/dm-core/types/text.rb +10 -0
- data/spec/integration/association_spec.rb +1215 -0
- data/spec/integration/association_through_spec.rb +150 -0
- data/spec/integration/associations/many_to_many_spec.rb +171 -0
- data/spec/integration/associations/many_to_one_spec.rb +123 -0
- data/spec/integration/associations/one_to_many_spec.rb +66 -0
- data/spec/integration/auto_migrations_spec.rb +398 -0
- data/spec/integration/collection_spec.rb +1015 -0
- data/spec/integration/data_objects_adapter_spec.rb +32 -0
- data/spec/integration/model_spec.rb +68 -0
- data/spec/integration/mysql_adapter_spec.rb +85 -0
- data/spec/integration/postgres_adapter_spec.rb +732 -0
- data/spec/integration/property_spec.rb +224 -0
- data/spec/integration/query_spec.rb +376 -0
- data/spec/integration/repository_spec.rb +57 -0
- data/spec/integration/resource_spec.rb +324 -0
- data/spec/integration/sqlite3_adapter_spec.rb +352 -0
- data/spec/integration/sti_spec.rb +185 -0
- data/spec/integration/transaction_spec.rb +75 -0
- data/spec/integration/type_spec.rb +149 -0
- data/spec/lib/mock_adapter.rb +27 -0
- data/spec/spec_helper.rb +112 -0
- data/spec/unit/adapters/abstract_adapter_spec.rb +133 -0
- data/spec/unit/adapters/adapter_shared_spec.rb +15 -0
- data/spec/unit/adapters/data_objects_adapter_spec.rb +627 -0
- data/spec/unit/adapters/postgres_adapter_spec.rb +125 -0
- data/spec/unit/associations/many_to_many_spec.rb +14 -0
- data/spec/unit/associations/many_to_one_spec.rb +138 -0
- data/spec/unit/associations/one_to_many_spec.rb +385 -0
- data/spec/unit/associations/one_to_one_spec.rb +7 -0
- data/spec/unit/associations/relationship_spec.rb +67 -0
- data/spec/unit/associations_spec.rb +205 -0
- data/spec/unit/auto_migrations_spec.rb +110 -0
- data/spec/unit/collection_spec.rb +174 -0
- data/spec/unit/data_mapper_spec.rb +21 -0
- data/spec/unit/identity_map_spec.rb +126 -0
- data/spec/unit/is_spec.rb +80 -0
- data/spec/unit/migrator_spec.rb +33 -0
- data/spec/unit/model_spec.rb +339 -0
- data/spec/unit/naming_conventions_spec.rb +28 -0
- data/spec/unit/property_set_spec.rb +96 -0
- data/spec/unit/property_spec.rb +447 -0
- data/spec/unit/query_spec.rb +485 -0
- data/spec/unit/repository_spec.rb +93 -0
- data/spec/unit/resource_spec.rb +557 -0
- data/spec/unit/scope_spec.rb +131 -0
- data/spec/unit/transaction_spec.rb +493 -0
- data/spec/unit/type_map_spec.rb +114 -0
- data/spec/unit/type_spec.rb +119 -0
- metadata +187 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
|
3
|
+
|
|
4
|
+
if HAS_SQLITE3
|
|
5
|
+
describe DataMapper::AutoMigrations, '.auto_migrate! on STI models with sqlite3' do
|
|
6
|
+
before :all do
|
|
7
|
+
@adapter = repository(:sqlite3).adapter
|
|
8
|
+
|
|
9
|
+
@property_class = Struct.new(:name, :type, :nullable, :default, :serial)
|
|
10
|
+
|
|
11
|
+
class Book
|
|
12
|
+
include DataMapper::Resource
|
|
13
|
+
|
|
14
|
+
property :id, Serial
|
|
15
|
+
property :title, String, :nullable => false
|
|
16
|
+
property :isbn, Integer, :nullable => false
|
|
17
|
+
property :class_type, Discriminator
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class Propaganda < Book
|
|
21
|
+
property :marxist, Boolean, :nullable => false, :default => false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class Fiction < Book
|
|
25
|
+
property :series, String
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class ShortStory < Fiction
|
|
29
|
+
property :moral, String
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class ScienceFiction < Fiction
|
|
33
|
+
property :aliens, Boolean
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class SpaceWestern < ScienceFiction
|
|
37
|
+
property :cowboys, Boolean
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "with a parent class" do
|
|
42
|
+
before :all do
|
|
43
|
+
Book.auto_migrate!(:sqlite3).should be_true
|
|
44
|
+
|
|
45
|
+
@table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
|
|
46
|
+
default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
|
|
47
|
+
nil
|
|
48
|
+
else
|
|
49
|
+
/^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
property = @property_class.new(
|
|
53
|
+
column.name,
|
|
54
|
+
column.type.upcase,
|
|
55
|
+
column.notnull == 0,
|
|
56
|
+
default,
|
|
57
|
+
column.pk == 1 # in SQLite3 the serial key is also primary
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
ts.update(property.name => property)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
@index_list = @adapter.query('PRAGMA index_list("books")')
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should create the child class property columns" do
|
|
67
|
+
@table_set.keys.should include("series", "marxist")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should create all property columns of the child classes in the inheritance tree" do
|
|
71
|
+
@table_set.keys.should include("moral")
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe "with a child class" do
|
|
76
|
+
before :all do
|
|
77
|
+
Propaganda.auto_migrate!(:sqlite3).should be_true
|
|
78
|
+
|
|
79
|
+
@table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
|
|
80
|
+
default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
|
|
81
|
+
nil
|
|
82
|
+
else
|
|
83
|
+
/^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
property = @property_class.new(
|
|
87
|
+
column.name,
|
|
88
|
+
column.type.upcase,
|
|
89
|
+
column.notnull == 0,
|
|
90
|
+
default,
|
|
91
|
+
column.pk == 1 # in SQLite3 the serial key is also primary
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
ts.update(property.name => property)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
@index_list = @adapter.query('PRAGMA index_list("books")')
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "should create the parent class' property columns" do
|
|
101
|
+
@table_set.keys.should include("id", "title", "isbn")
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
describe "with a child class with it's own child class" do
|
|
106
|
+
before :all do
|
|
107
|
+
Fiction.auto_migrate!(:sqlite3).should be_true
|
|
108
|
+
|
|
109
|
+
@table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
|
|
110
|
+
default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
|
|
111
|
+
nil
|
|
112
|
+
else
|
|
113
|
+
/^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
property = @property_class.new(
|
|
117
|
+
column.name,
|
|
118
|
+
column.type.upcase,
|
|
119
|
+
column.notnull == 0,
|
|
120
|
+
default,
|
|
121
|
+
column.pk == 1 # in SQLite3 the serial key is also primary
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
ts.update(property.name => property)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
@index_list = @adapter.query('PRAGMA index_list("books")')
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it "should create the parent class' property columns" do
|
|
131
|
+
@table_set.keys.should include("id", "title", "isbn")
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "should create the child class' property columns" do
|
|
135
|
+
@table_set.keys.should include("moral")
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe "with a nephew class" do
|
|
140
|
+
before :all do
|
|
141
|
+
ShortStory.auto_migrate!(:sqlite3).should be_true
|
|
142
|
+
|
|
143
|
+
@table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
|
|
144
|
+
default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
|
|
145
|
+
nil
|
|
146
|
+
else
|
|
147
|
+
/^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
property = @property_class.new(
|
|
151
|
+
column.name,
|
|
152
|
+
column.type.upcase,
|
|
153
|
+
column.notnull == 0,
|
|
154
|
+
default,
|
|
155
|
+
column.pk == 1 # in SQLite3 the serial key is also primary
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
ts.update(property.name => property)
|
|
159
|
+
end
|
|
160
|
+
@index_list = @adapter.query('PRAGMA index_list("books")')
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
it "should create the grandparent class' property columns" do
|
|
165
|
+
@table_set.keys.should include("id", "title", "isbn")
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "should create the uncle class' property columns" do
|
|
169
|
+
@table_set.keys.should include("marxist")
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
describe "with a great-grandchild class" do
|
|
174
|
+
it "should inherit its parent's properties" do
|
|
175
|
+
SpaceWestern.properties[:aliens].should_not be_nil
|
|
176
|
+
end
|
|
177
|
+
it "should inherit its grandparent's properties" do
|
|
178
|
+
SpaceWestern.properties[:series].should_not be_nil
|
|
179
|
+
end
|
|
180
|
+
it "should inherit its great-granparent's properties" do
|
|
181
|
+
SpaceWestern.properties[:title].should_not be_nil
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
# transaction capable adapters
|
|
4
|
+
ADAPTERS = []
|
|
5
|
+
ADAPTERS << :postgres if HAS_POSTGRES
|
|
6
|
+
ADAPTERS << :mysql if HAS_MYSQL
|
|
7
|
+
ADAPTERS << :sqlite3 if HAS_SQLITE3
|
|
8
|
+
|
|
9
|
+
if ADAPTERS.any?
|
|
10
|
+
class Sputnik
|
|
11
|
+
include DataMapper::Resource
|
|
12
|
+
|
|
13
|
+
property :id, Serial
|
|
14
|
+
property :name, DM::Text
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe DataMapper::Transaction do
|
|
18
|
+
before :all do
|
|
19
|
+
@repositories = []
|
|
20
|
+
|
|
21
|
+
ADAPTERS.each do |name|
|
|
22
|
+
@repositories << repository(name)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
before :each do
|
|
27
|
+
ADAPTERS.each do |name|
|
|
28
|
+
Sputnik.auto_migrate!(name)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should commit changes to all involved adapters on a two phase commit" do
|
|
33
|
+
DataMapper::Transaction.new(*@repositories) do
|
|
34
|
+
ADAPTERS.each do |name|
|
|
35
|
+
repository(name) { Sputnik.create!(:name => 'hepp') }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
ADAPTERS.each do |name|
|
|
40
|
+
repository(name) { Sputnik.all.size.should == 1 }
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should not commit any changes if the block raises an exception" do
|
|
45
|
+
lambda do
|
|
46
|
+
DataMapper::Transaction.new(*@repositories) do
|
|
47
|
+
ADAPTERS.each do |name|
|
|
48
|
+
repository(name) { Sputnik.create!(:name => 'hepp') }
|
|
49
|
+
end
|
|
50
|
+
raise "plur"
|
|
51
|
+
end
|
|
52
|
+
end.should raise_error(Exception, /plur/)
|
|
53
|
+
|
|
54
|
+
ADAPTERS.each do |name|
|
|
55
|
+
repository(name) { Sputnik.all.size.should == 0 }
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should not commit any changes if any of the adapters doesnt prepare properly" do
|
|
60
|
+
lambda do
|
|
61
|
+
DataMapper::Transaction.new(*@repositories) do |transaction|
|
|
62
|
+
ADAPTERS.each do |name|
|
|
63
|
+
repository(name) { Sputnik.create!(:name => 'hepp') }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
transaction.primitive_for(@repositories.last.adapter).should_receive(:prepare).and_throw(Exception.new("I am the famous test exception"))
|
|
67
|
+
end
|
|
68
|
+
end.should raise_error(Exception, /I am the famous test exception/)
|
|
69
|
+
|
|
70
|
+
ADAPTERS.each do |name|
|
|
71
|
+
repository(name) { Sputnik.all.size.should == 0 }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
gem 'fastercsv', '>=1.2.3'
|
|
4
|
+
require 'fastercsv'
|
|
5
|
+
|
|
6
|
+
if ADAPTER
|
|
7
|
+
module TypeTests
|
|
8
|
+
class Impostor < DataMapper::Type
|
|
9
|
+
primitive String
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class Coconut
|
|
13
|
+
include DataMapper::Resource
|
|
14
|
+
|
|
15
|
+
storage_names[ADAPTER] = 'coconuts'
|
|
16
|
+
|
|
17
|
+
def self.default_repository_name
|
|
18
|
+
ADAPTER
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
property :id, Serial
|
|
22
|
+
property :faked, Impostor
|
|
23
|
+
property :active, Boolean
|
|
24
|
+
property :note, Text
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Lemon
|
|
29
|
+
include DataMapper::Resource
|
|
30
|
+
|
|
31
|
+
def self.default_repository_name
|
|
32
|
+
ADAPTER
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
property :id, Serial
|
|
36
|
+
property :color, String
|
|
37
|
+
property :deleted_at, DataMapper::Types::ParanoidDateTime
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class Lime
|
|
41
|
+
include DataMapper::Resource
|
|
42
|
+
|
|
43
|
+
def self.default_repository_name
|
|
44
|
+
ADAPTER
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
property :id, Serial
|
|
48
|
+
property :color, String
|
|
49
|
+
property :deleted_at, DataMapper::Types::ParanoidBoolean
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe DataMapper::Type, "with #{ADAPTER}" do
|
|
53
|
+
before do
|
|
54
|
+
TypeTests::Coconut.auto_migrate!(ADAPTER)
|
|
55
|
+
|
|
56
|
+
@document = <<-EOS.margin
|
|
57
|
+
NAME, RATING, CONVENIENCE
|
|
58
|
+
Freebird's, 3, 3
|
|
59
|
+
Whataburger, 1, 5
|
|
60
|
+
Jimmy John's, 3, 4
|
|
61
|
+
Mignon, 5, 2
|
|
62
|
+
Fuzi Yao's, 5, 1
|
|
63
|
+
Blue Goose, 5, 1
|
|
64
|
+
EOS
|
|
65
|
+
|
|
66
|
+
@stuff = YAML::dump({ 'Happy Cow!' => true, 'Sad Cow!' => false })
|
|
67
|
+
|
|
68
|
+
@active = true
|
|
69
|
+
@note = "This is a note on our ol' guy bob"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "should instantiate an object with custom types" do
|
|
73
|
+
coconut = TypeTests::Coconut.new(:faked => 'bob', :active => @active, :note => @note)
|
|
74
|
+
coconut.faked.should == 'bob'
|
|
75
|
+
coconut.active.should be_a_kind_of(TrueClass)
|
|
76
|
+
coconut.note.should be_a_kind_of(String)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should CRUD an object with custom types" do
|
|
80
|
+
repository(ADAPTER) do
|
|
81
|
+
coconut = TypeTests::Coconut.new(:faked => 'bob', :active => @active, :note => @note)
|
|
82
|
+
coconut.save.should be_true
|
|
83
|
+
coconut.id.should_not be_nil
|
|
84
|
+
|
|
85
|
+
fred = TypeTests::Coconut.get!(coconut.id)
|
|
86
|
+
fred.faked.should == 'bob'
|
|
87
|
+
fred.active.should be_a_kind_of(TrueClass)
|
|
88
|
+
fred.note.should be_a_kind_of(String)
|
|
89
|
+
|
|
90
|
+
note = "Seems like bob is just mockin' around"
|
|
91
|
+
fred.note = note
|
|
92
|
+
|
|
93
|
+
fred.save.should be_true
|
|
94
|
+
|
|
95
|
+
active = false
|
|
96
|
+
fred.active = active
|
|
97
|
+
|
|
98
|
+
fred.save.should be_true
|
|
99
|
+
|
|
100
|
+
# Can't call coconut.reload since coconut.collection isn't setup.
|
|
101
|
+
mac = TypeTests::Coconut.get!(fred.id)
|
|
102
|
+
mac.active.should == active
|
|
103
|
+
mac.note.should == note
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "should respect paranoia with a datetime" do
|
|
108
|
+
Lemon.auto_migrate!(ADAPTER)
|
|
109
|
+
|
|
110
|
+
lemon = nil
|
|
111
|
+
|
|
112
|
+
repository(ADAPTER) do |repository|
|
|
113
|
+
lemon = Lemon.new
|
|
114
|
+
lemon.color = 'green'
|
|
115
|
+
|
|
116
|
+
lemon.save
|
|
117
|
+
lemon.destroy
|
|
118
|
+
|
|
119
|
+
lemon.deleted_at.should be_kind_of(DateTime)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
repository(ADAPTER) do |repository|
|
|
123
|
+
Lemon.all.should be_empty
|
|
124
|
+
Lemon.get(lemon.id).should be_nil
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "should respect paranoia with a boolean" do
|
|
129
|
+
Lime.auto_migrate!(ADAPTER)
|
|
130
|
+
|
|
131
|
+
lime = nil
|
|
132
|
+
|
|
133
|
+
repository(ADAPTER) do |repository|
|
|
134
|
+
lime = Lime.new
|
|
135
|
+
lime.color = 'green'
|
|
136
|
+
|
|
137
|
+
lime.save
|
|
138
|
+
lime.destroy
|
|
139
|
+
|
|
140
|
+
lime.deleted_at.should be_kind_of(TrueClass)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
repository(ADAPTER) do |repository|
|
|
144
|
+
Lime.all.should be_empty
|
|
145
|
+
Lime.get(lime.id).should be_nil
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module DataMapper
|
|
2
|
+
module Adapters
|
|
3
|
+
class MockAdapter < DataMapper::Adapters::DataObjectsAdapter
|
|
4
|
+
|
|
5
|
+
def create(resources)
|
|
6
|
+
1
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def exists?(storage_name)
|
|
10
|
+
true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
module DataObjects
|
|
18
|
+
module Mock
|
|
19
|
+
|
|
20
|
+
def self.logger
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.logger=(value)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
gem 'rspec', '>=1.1.3'
|
|
3
|
+
require 'spec'
|
|
4
|
+
require 'pathname'
|
|
5
|
+
|
|
6
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'lib/dm-core'
|
|
7
|
+
require DataMapper.root / 'spec' / 'lib' / 'mock_adapter'
|
|
8
|
+
|
|
9
|
+
# setup mock adapters
|
|
10
|
+
[ :default, :mock, :legacy, :west_coast, :east_coast ].each do |repository_name|
|
|
11
|
+
DataMapper.setup(repository_name, "mock://localhost/#{repository_name}")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def setup_adapter(name, default_uri)
|
|
15
|
+
begin
|
|
16
|
+
DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
|
|
17
|
+
Object.const_set('ADAPTER', ENV['ADAPTER'].to_sym) if name.to_s == ENV['ADAPTER']
|
|
18
|
+
true
|
|
19
|
+
rescue Exception => e
|
|
20
|
+
if name.to_s == ENV['ADAPTER']
|
|
21
|
+
Object.const_set('ADAPTER', nil)
|
|
22
|
+
warn "Could not load #{name} adapter: #{e}"
|
|
23
|
+
end
|
|
24
|
+
false
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
ENV['ADAPTER'] ||= 'sqlite3'
|
|
29
|
+
|
|
30
|
+
HAS_SQLITE3 = setup_adapter(:sqlite3, 'sqlite3::memory:')
|
|
31
|
+
HAS_MYSQL = setup_adapter(:mysql, 'mysql://localhost/dm_core_test')
|
|
32
|
+
HAS_POSTGRES = setup_adapter(:postgres, 'postgres://postgres@localhost/dm_core_test')
|
|
33
|
+
|
|
34
|
+
DataMapper::Logger.new(nil, :debug)
|
|
35
|
+
|
|
36
|
+
class Article
|
|
37
|
+
include DataMapper::Resource
|
|
38
|
+
|
|
39
|
+
property :id, Serial
|
|
40
|
+
property :blog_id, Integer
|
|
41
|
+
property :created_at, DateTime
|
|
42
|
+
property :author, String
|
|
43
|
+
property :title, String
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class Comment
|
|
47
|
+
include DataMapper::Resource
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class NormalClass
|
|
51
|
+
# should not include DataMapper::Resource
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# ==========================
|
|
55
|
+
# Used for Association specs
|
|
56
|
+
class Vehicle
|
|
57
|
+
include DataMapper::Resource
|
|
58
|
+
|
|
59
|
+
property :id, Serial
|
|
60
|
+
property :name, String
|
|
61
|
+
|
|
62
|
+
class << self
|
|
63
|
+
attr_accessor :mock_relationship
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class Manufacturer
|
|
68
|
+
include DataMapper::Resource
|
|
69
|
+
|
|
70
|
+
property :id, Serial
|
|
71
|
+
property :name, String
|
|
72
|
+
|
|
73
|
+
class << self
|
|
74
|
+
attr_accessor :mock_relationship
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
class Supplier
|
|
79
|
+
include DataMapper::Resource
|
|
80
|
+
|
|
81
|
+
property :id, Serial
|
|
82
|
+
property :name, String
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
class Class
|
|
86
|
+
def publicize_methods
|
|
87
|
+
klass = class << self; self; end
|
|
88
|
+
|
|
89
|
+
saved_private_class_methods = klass.private_instance_methods
|
|
90
|
+
saved_protected_class_methods = klass.protected_instance_methods
|
|
91
|
+
saved_private_instance_methods = self.private_instance_methods
|
|
92
|
+
saved_protected_instance_methods = self.protected_instance_methods
|
|
93
|
+
|
|
94
|
+
self.class_eval do
|
|
95
|
+
klass.send(:public, *saved_private_class_methods)
|
|
96
|
+
klass.send(:public, *saved_protected_class_methods)
|
|
97
|
+
public(*saved_private_instance_methods)
|
|
98
|
+
public(*saved_protected_instance_methods)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
begin
|
|
102
|
+
yield
|
|
103
|
+
ensure
|
|
104
|
+
self.class_eval do
|
|
105
|
+
klass.send(:private, *saved_private_class_methods)
|
|
106
|
+
klass.send(:protected, *saved_protected_class_methods)
|
|
107
|
+
private(*saved_private_instance_methods)
|
|
108
|
+
protected(*saved_protected_instance_methods)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|