sequel_model 0.1
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 +3 -0
- data/COPYING +18 -0
- data/README +251 -0
- data/Rakefile +146 -0
- data/lib/sequel_model.rb +326 -0
- data/lib/sequel_model/base.rb +97 -0
- data/lib/sequel_model/caching.rb +42 -0
- data/lib/sequel_model/hooks.rb +122 -0
- data/lib/sequel_model/plugins.rb +44 -0
- data/lib/sequel_model/pretty_table.rb +73 -0
- data/lib/sequel_model/record.rb +309 -0
- data/lib/sequel_model/relations.rb +107 -0
- data/lib/sequel_model/schema.rb +52 -0
- data/lib/sequel_model/validations.rb +117 -0
- data/spec/base_spec.rb +150 -0
- data/spec/caching_spec.rb +150 -0
- data/spec/hooks_spec.rb +107 -0
- data/spec/model_spec.rb +564 -0
- data/spec/plugins_spec.rb +61 -0
- data/spec/rcov.opts +4 -0
- data/spec/record_spec.rb +362 -0
- data/spec/relations_spec.rb +150 -0
- data/spec/schema_spec.rb +82 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/validations_spec.rb +294 -0
- metadata +111 -0
data/spec/schema_spec.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe Sequel::Model, "table_exists?" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
MODEL_DB.reset
|
7
|
+
@model = Class.new(Sequel::Model(:items))
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should get the table name and question the model's db if table_exists?" do
|
11
|
+
@model.should_receive(:table_name).and_return(:items)
|
12
|
+
@model.db.should_receive(:table_exists?)
|
13
|
+
@model.table_exists?
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
describe Sequel::Model, "create_table" do
|
19
|
+
|
20
|
+
before(:each) do
|
21
|
+
MODEL_DB.reset
|
22
|
+
@model = Class.new(Sequel::Model(:items))
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should get the create table SQL list from the db and execute it line by line" do
|
26
|
+
#db.create_table_sql_list(table_name, *schema.create_info).each {|s| db << s}
|
27
|
+
@model.should_receive(:table_name).and_return(:items)
|
28
|
+
@model.schema.should_receive(:create_info)
|
29
|
+
@model.db.should_receive(:create_table_sql_list)
|
30
|
+
pending("Finish specing this")
|
31
|
+
@model.create_table
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe Sequel::Model, "drop_table" do
|
37
|
+
|
38
|
+
before(:each) do
|
39
|
+
MODEL_DB.reset
|
40
|
+
@model = Class.new(Sequel::Model(:items))
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should get the drop table SQL for the associated table and then execute the SQL." do
|
44
|
+
@model.should_receive(:table_name).and_return(:items)
|
45
|
+
@model.db.should_receive(:drop_table_sql).with(:items)
|
46
|
+
@model.db.should_receive(:execute).and_return(:true)
|
47
|
+
@model.drop_table
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
describe Sequel::Model, "create_table!" do
|
53
|
+
|
54
|
+
before(:each) do
|
55
|
+
MODEL_DB.reset
|
56
|
+
@model = Class.new(Sequel::Model(:items))
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should drop table if it exists and then create the table" do
|
60
|
+
@model.should_receive(:table_exists?).and_return(true)
|
61
|
+
@model.should_receive(:drop_table).and_return(true)
|
62
|
+
@model.should_receive(:create_table).and_return(true)
|
63
|
+
|
64
|
+
@model.create_table!
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
describe Sequel::Model, "recreate_table" do
|
70
|
+
|
71
|
+
before(:each) do
|
72
|
+
MODEL_DB.reset
|
73
|
+
@model = Class.new(Sequel::Model(:items))
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should raise a depreciation warning and then call create_table!" do
|
77
|
+
@model.should_receive(:warn)
|
78
|
+
@model.should_receive(:create_table!).and_return(true)
|
79
|
+
@model.recreate_table
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require File.join(File.dirname(__FILE__), "../lib/sequel_model")
|
3
|
+
|
4
|
+
class MockDataset < Sequel::Dataset
|
5
|
+
def insert(*args)
|
6
|
+
@db.execute insert_sql(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def update(*args)
|
10
|
+
@db.execute update_sql(*args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def fetch_rows(sql)
|
14
|
+
@db.execute(sql)
|
15
|
+
yield({:id => 1, :x => 1})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class MockDatabase < Sequel::Database
|
20
|
+
attr_reader :sqls
|
21
|
+
|
22
|
+
def execute(sql)
|
23
|
+
@sqls ||= []
|
24
|
+
@sqls << sql
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset
|
28
|
+
@sqls = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def transaction; yield; end
|
32
|
+
|
33
|
+
def dataset; MockDataset.new(self); end
|
34
|
+
end
|
35
|
+
|
36
|
+
Sequel::Model.db = MODEL_DB = MockDatabase.new
|
@@ -0,0 +1,294 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe Sequel::Model, "Validations" do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
class Person < Sequel::Model(:people)
|
7
|
+
def columns
|
8
|
+
[:id,:name,:first_name,:last_name,:middle_name,:initials,:age, :terms]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Smurf < Person
|
13
|
+
end
|
14
|
+
|
15
|
+
class Cow < Sequel::Model(:cows)
|
16
|
+
def columns
|
17
|
+
[:id, :name, :got_milk]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class User < Sequel::Model(:users)
|
22
|
+
def columns
|
23
|
+
[:id, :username, :password]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Address < Sequel::Model(:addresses)
|
28
|
+
def columns
|
29
|
+
[:id, :zip_code]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should have a hook before validating" do
|
35
|
+
class Person < Sequel::Model(:people)
|
36
|
+
before_validation do
|
37
|
+
self.name = "default name"
|
38
|
+
end
|
39
|
+
validations.clear
|
40
|
+
validates_presence_of :name
|
41
|
+
end
|
42
|
+
|
43
|
+
@person = Person.new
|
44
|
+
@person.valid?.should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should include errors from other models" do
|
48
|
+
pending("Waiting for Wayne's amazing associations!")
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should validate the acceptance of a column" do
|
52
|
+
class Cow < Sequel::Model(:cows)
|
53
|
+
validations.clear
|
54
|
+
validates_acceptance_of :got_milk
|
55
|
+
end
|
56
|
+
|
57
|
+
@cow = Cow.new
|
58
|
+
@cow.valid?.should be_false
|
59
|
+
@cow.errors.on(:got_milk).should == "must be accepted"
|
60
|
+
|
61
|
+
@cow.got_milk = "true"
|
62
|
+
@cow.valid?.should be_true
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should validate the confirmation of a column" do
|
66
|
+
class User < Sequel::Model(:users)
|
67
|
+
def password_confirmation
|
68
|
+
"test"
|
69
|
+
end
|
70
|
+
|
71
|
+
validations.clear
|
72
|
+
validates_confirmation_of :password
|
73
|
+
end
|
74
|
+
|
75
|
+
@user = User.new
|
76
|
+
@user.valid?.should be_false
|
77
|
+
@user.errors.on(:password).should == "doesn't match confirmation"
|
78
|
+
|
79
|
+
@user.password = "test"
|
80
|
+
@user.valid?.should be_true
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should validate each with logic" do
|
84
|
+
class ZipCodeService; end
|
85
|
+
|
86
|
+
class Address < Sequel::Model(:addresses)
|
87
|
+
validations.clear
|
88
|
+
validates_each :zip_code, :logic => lambda { errors.add(:zip_code, "is not valid") unless ZipCodeService.allows(zip_code) }
|
89
|
+
end
|
90
|
+
|
91
|
+
@address = Address.new :zip_code => "48108"
|
92
|
+
ZipCodeService.should_receive(:allows).with("48108").and_return(false)
|
93
|
+
@address.valid?.should be_false
|
94
|
+
@address.errors.on(:zip_code).should == "is not valid"
|
95
|
+
|
96
|
+
@address2 = Address.new :zip_code => "48104"
|
97
|
+
ZipCodeService.should_receive(:allows).with("48104").and_return(true)
|
98
|
+
@address2.valid?.should be_true
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should validate format of column" do
|
102
|
+
class Person < Sequel::Model(:people)
|
103
|
+
validates_format_of :first_name, :with => /^[a-zA-Z]+$/
|
104
|
+
end
|
105
|
+
|
106
|
+
@person = Person.new :first_name => "Lancelot99"
|
107
|
+
@person.valid?.should be_false
|
108
|
+
@person = Person.new :first_name => "Anita"
|
109
|
+
@person.valid?.should be_true
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should allow for :with_exactly => /[a-zA-Z/, which wraps the supplied regex with ^<regex>$" do
|
113
|
+
pending("TODO: Add this option to Validatable#validates_format_of")
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should validate length of column" do
|
117
|
+
class Person < Sequel::Model(:people)
|
118
|
+
validations.clear
|
119
|
+
validates_length_of :first_name, :maximum => 30
|
120
|
+
validates_length_of :last_name, :minimum => 30
|
121
|
+
validates_length_of :middle_name, :within => 1..5
|
122
|
+
validates_length_of :initials, :is => 2
|
123
|
+
end
|
124
|
+
|
125
|
+
@person = Person.new(
|
126
|
+
:first_name => "Anamethatiswaytofreakinglongandwayoverthirtycharacters",
|
127
|
+
:last_name => "Alastnameunderthirtychars",
|
128
|
+
:initials => "LGC",
|
129
|
+
:middle_name => "danger"
|
130
|
+
)
|
131
|
+
|
132
|
+
@person.valid?.should be_false
|
133
|
+
@person.errors.on(:first_name).should == "is invalid"
|
134
|
+
@person.errors.on(:last_name).should == "is invalid"
|
135
|
+
@person.errors.on(:initials).should == "is invalid"
|
136
|
+
@person.errors.on(:middle_name).should == "is invalid"
|
137
|
+
|
138
|
+
@person.first_name = "Lancelot"
|
139
|
+
@person.last_name = "1234567890123456789012345678901"
|
140
|
+
@person.initials = "LC"
|
141
|
+
@person.middle_name = "Will"
|
142
|
+
@person.valid?.should be_true
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should validate numericality of column" do
|
146
|
+
class Person < Sequel::Model(:people)
|
147
|
+
validations.clear
|
148
|
+
validates_numericality_of :age
|
149
|
+
end
|
150
|
+
|
151
|
+
@person = Person.new :age => "Twenty"
|
152
|
+
@person.valid?.should be_false
|
153
|
+
@person.errors.on(:age).should == "must be a number"
|
154
|
+
|
155
|
+
@person.age = 20
|
156
|
+
@person.valid?.should be_true
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should validate the presence of a column" do
|
160
|
+
class Cow < Sequel::Model(:cows)
|
161
|
+
validations.clear
|
162
|
+
validates_presence_of :name
|
163
|
+
end
|
164
|
+
|
165
|
+
@cow = Cow.new
|
166
|
+
@cow.valid?.should be_false
|
167
|
+
@cow.errors.on(:name).should == "can't be empty"
|
168
|
+
@cow.errors.full_messages.first.should == "Name can't be empty"
|
169
|
+
|
170
|
+
@cow.name = "Betsy"
|
171
|
+
@cow.valid?.should be_true
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should validate true for a column" do
|
175
|
+
class Person < Sequel::Model(:people)
|
176
|
+
validations.clear
|
177
|
+
validates_true_for :first_name, :logic => lambda { first_name == "Alison" }
|
178
|
+
end
|
179
|
+
|
180
|
+
@person = Person.new :first_name => "Nina"
|
181
|
+
@person.valid?.should be_false
|
182
|
+
@person.errors.on(:first_name).should == "is invalid"
|
183
|
+
|
184
|
+
@person.first_name = "Alison"
|
185
|
+
@person.valid?.should be_true
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should have a validates block that calls multple validations" do
|
189
|
+
class Person < Sequel::Model(:people)
|
190
|
+
validations.clear
|
191
|
+
validates do
|
192
|
+
format_of :first_name, :with => /^[a-zA-Z]+$/
|
193
|
+
length_of :first_name, :maximum => 30
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
Person.validations.length.should eql(2)
|
198
|
+
|
199
|
+
@person = Person.new :first_name => "Lancelot99"
|
200
|
+
@person.valid?.should be_false
|
201
|
+
|
202
|
+
@person2 = Person.new :first_name => "Wayne"
|
203
|
+
@person2.valid?.should be_true
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should require and include the validatable gem" do
|
207
|
+
Gem.loaded_specs["validatable"].should_not be_nil
|
208
|
+
Sequel::Model.should respond_to(:validates_format_of) # validatable gem
|
209
|
+
Sequel::Model.should respond_to(:validations) # Validations module
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should description" do
|
213
|
+
Sequel::Model.should_receive(:require).with("validatable").and_raise(LoadError)
|
214
|
+
STDERR.should_receive(:puts)
|
215
|
+
load File.join(File.dirname(__FILE__), "../lib/sequel_model/validations.rb")
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should allow 'longhand' validations direcly within the model." do
|
219
|
+
lambda {
|
220
|
+
class Person < Sequel::Model(:people)
|
221
|
+
validations.clear
|
222
|
+
validates_length_of :first_name, :maximum => 30
|
223
|
+
end
|
224
|
+
}.should_not raise_error
|
225
|
+
Person.validations.length.should eql(1)
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should validates do should allow shorthand method for every longhand validates_* method" do
|
229
|
+
class Person
|
230
|
+
validations.clear
|
231
|
+
validates do
|
232
|
+
format_of :first_name, :with => /^[a-zA-Z]+$/
|
233
|
+
length_of :first_name, :maximum => 30
|
234
|
+
presence_of :first_name
|
235
|
+
numericality_of :age
|
236
|
+
acceptance_of :terms
|
237
|
+
confirmation_of :password
|
238
|
+
true_for :first_name, :logic => lambda { first_name == "Alison" }
|
239
|
+
#validates_each :last_name, :logic => lambda { errors.add(:zip_code, "is not valid") unless ZipCodeService.allows(zip_code) }
|
240
|
+
#base
|
241
|
+
end
|
242
|
+
|
243
|
+
# Now check to make sure that each validation exists in the model's validations.
|
244
|
+
end
|
245
|
+
pending("finish this spec for each case")
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should define a has_validations? method which returns true if the model has validations, false otherwise" do
|
249
|
+
class Person < Sequel::Model(:people)
|
250
|
+
validations.clear
|
251
|
+
validates do
|
252
|
+
format_of :first_name, :with => /\w+/
|
253
|
+
length_of :first_name, :maximum => 30
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
class Smurf < Person
|
258
|
+
validations.clear
|
259
|
+
end
|
260
|
+
|
261
|
+
Person.should have_validations
|
262
|
+
Smurf.should_not have_validations
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
266
|
+
|
267
|
+
describe Sequel::Model, "validates" do
|
268
|
+
|
269
|
+
|
270
|
+
before(:all) do
|
271
|
+
class Person < Sequel::Model(:people)
|
272
|
+
def columns
|
273
|
+
[:id,:name,:first_name,:last_name,:middle_name,:initials,:age]
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should runs the validations block on the model & store as :default when only a validations block is passed in" do
|
279
|
+
pending
|
280
|
+
end
|
281
|
+
|
282
|
+
it "should store the block under the name passed in when both a name and a validations block are passed in" do
|
283
|
+
pending
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should return the stored validations block corresponding to the name given, if only a name is given (no block)" do
|
287
|
+
pending
|
288
|
+
end
|
289
|
+
|
290
|
+
it "should return true or false based on if validations exist on the model if no arguments are given" do
|
291
|
+
pending
|
292
|
+
end
|
293
|
+
|
294
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sequel_model
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sharon Rosner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2007-12-30 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: sequel
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0.5"
|
23
|
+
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: validatable
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: "0"
|
32
|
+
version:
|
33
|
+
description: Lightweight ORM for Ruby
|
34
|
+
email: ciconia@gmail.com
|
35
|
+
executables: []
|
36
|
+
|
37
|
+
extensions: []
|
38
|
+
|
39
|
+
extra_rdoc_files:
|
40
|
+
- README
|
41
|
+
- CHANGELOG
|
42
|
+
- COPYING
|
43
|
+
files:
|
44
|
+
- COPYING
|
45
|
+
- README
|
46
|
+
- Rakefile
|
47
|
+
- doc/rdoc
|
48
|
+
- spec/base_spec.rb
|
49
|
+
- spec/caching_spec.rb
|
50
|
+
- spec/hooks_spec.rb
|
51
|
+
- spec/model_spec.rb
|
52
|
+
- spec/plugins_spec.rb
|
53
|
+
- spec/rcov.opts
|
54
|
+
- spec/record_spec.rb
|
55
|
+
- spec/relations_spec.rb
|
56
|
+
- spec/schema_spec.rb
|
57
|
+
- spec/spec.opts
|
58
|
+
- spec/spec_helper.rb
|
59
|
+
- spec/validations_spec.rb
|
60
|
+
- lib/sequel_model
|
61
|
+
- lib/sequel_model/base.rb
|
62
|
+
- lib/sequel_model/caching.rb
|
63
|
+
- lib/sequel_model/hooks.rb
|
64
|
+
- lib/sequel_model/plugins.rb
|
65
|
+
- lib/sequel_model/pretty_table.rb
|
66
|
+
- lib/sequel_model/record.rb
|
67
|
+
- lib/sequel_model/relations.rb
|
68
|
+
- lib/sequel_model/schema.rb
|
69
|
+
- lib/sequel_model/validations.rb
|
70
|
+
- lib/sequel_model.rb
|
71
|
+
- CHANGELOG
|
72
|
+
has_rdoc: true
|
73
|
+
homepage: http://sequel.rubyforge.org
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options:
|
76
|
+
- --quiet
|
77
|
+
- --title
|
78
|
+
- "Sequel Model: Lightweight ORM for Ruby"
|
79
|
+
- --opname
|
80
|
+
- index.html
|
81
|
+
- --line-numbers
|
82
|
+
- --main
|
83
|
+
- README
|
84
|
+
- --inline-source
|
85
|
+
- --exclude
|
86
|
+
- ^(examples|extras)/
|
87
|
+
- --exclude
|
88
|
+
- lib/sequel.rb
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 1.8.4
|
96
|
+
version:
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: "0"
|
102
|
+
version:
|
103
|
+
requirements: []
|
104
|
+
|
105
|
+
rubyforge_project: sequel_model
|
106
|
+
rubygems_version: 1.0.1
|
107
|
+
signing_key:
|
108
|
+
specification_version: 2
|
109
|
+
summary: Lightweight ORM for Ruby
|
110
|
+
test_files: []
|
111
|
+
|