sequel 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +56 -0
- data/README +257 -154
- data/Rakefile +8 -16
- data/lib/sequel_model.rb +15 -257
- data/lib/sequel_model/associations.rb +70 -33
- data/lib/sequel_model/base.rb +80 -35
- data/lib/sequel_model/caching.rb +3 -3
- data/lib/sequel_model/deprecated.rb +81 -0
- data/lib/sequel_model/eager_loading.rb +303 -43
- data/lib/sequel_model/hooks.rb +29 -25
- data/lib/sequel_model/inflections.rb +112 -0
- data/lib/sequel_model/inflector.rb +279 -0
- data/lib/sequel_model/plugins.rb +15 -14
- data/lib/sequel_model/record.rb +87 -75
- data/lib/sequel_model/schema.rb +2 -0
- data/lib/sequel_model/validations.rb +300 -2
- data/spec/associations_spec.rb +175 -9
- data/spec/base_spec.rb +37 -18
- data/spec/caching_spec.rb +7 -4
- data/spec/deprecated_relations_spec.rb +3 -43
- data/spec/eager_loading_spec.rb +295 -7
- data/spec/hooks_spec.rb +7 -4
- data/spec/inflector_spec.rb +34 -0
- data/spec/model_spec.rb +30 -53
- data/spec/record_spec.rb +191 -33
- data/spec/spec_helper.rb +17 -2
- data/spec/validations_spec.rb +414 -15
- metadata +7 -22
- data/lib/sequel_model/pretty_table.rb +0 -73
data/CHANGELOG
CHANGED
@@ -1,3 +1,59 @@
|
|
1
|
+
=== HEAD
|
2
|
+
|
3
|
+
* Make the validation errors API compatible with Merb (Inviz)
|
4
|
+
|
5
|
+
* Add validates_uniqueness_of, for protecting against duplicate entries in the database (neaf, jeremyevans)
|
6
|
+
|
7
|
+
* Alias Model#dataset= to Model#set_dataset (tmm1)
|
8
|
+
|
9
|
+
* Make some Model class methods private: def_hook_method, hooks, add_hook, plugin_module, plugin_gem (jeremyevans)
|
10
|
+
|
11
|
+
* Add the eager! and eager_graph! mutation methods to model datasets (jeremyevans)
|
12
|
+
|
13
|
+
* Remove Model.database_opened (jeremyevans)
|
14
|
+
|
15
|
+
* Remove Model.super_dataset (jeremyevans)
|
16
|
+
|
17
|
+
* Deprecate .create_with_params, .create_with, #set, #update, #update_with, and #new_record from Sequel::Model (jeremyevans)
|
18
|
+
|
19
|
+
* Add Model.def_dataset_method, for defining methods on the model that reference methods on the dataset (jeremyevans)
|
20
|
+
|
21
|
+
* Deprecate Model.method_missing, add dataset methods to Model via metaprogramming (jeremyevans)
|
22
|
+
|
23
|
+
* Remove Model.join, so it is the same as Dataset#join (jeremyevans)
|
24
|
+
|
25
|
+
* Use reciprocal associations for all types of associations in the getter/setter/add_/remove_ methods (jeremyevans)
|
26
|
+
|
27
|
+
* Fix many_to_one associations to cache negative lookups (jeremyevans)
|
28
|
+
|
29
|
+
* Change Model#=== to always be false if the primary key is nil (jeremyevans)
|
30
|
+
|
31
|
+
* Add Model#hash, which should be unique for a given class and primary key (or values if primary key is nil) (jeremyevans)
|
32
|
+
|
33
|
+
* Add Model#eql? as a alias to Model#== (jeremyevans)
|
34
|
+
|
35
|
+
* Make Model#reload clear any cached associations (jeremyevans)
|
36
|
+
|
37
|
+
* No longer depend on the assistance gem, merge the Inflector and Validations code (jeremyevans)
|
38
|
+
|
39
|
+
* Add Model#set_with_params, which is Model#update_with_params without the save (jeremyevans)
|
40
|
+
|
41
|
+
* Fix Model#destroy so that it returns self, not the result of after_destroy (jeremyevans)
|
42
|
+
|
43
|
+
* Define Model column accessors in set_dataset, so they should always be avaiable, deprecate Model#method_missing (jeremyevans)
|
44
|
+
|
45
|
+
* Add eager loading of associations via new sequel_core object graphing feature (jeremyevans)
|
46
|
+
|
47
|
+
* Fix many_to_many associations with classes inside modules without an explicit join table (jeremyevans)
|
48
|
+
|
49
|
+
* Allow creation of new records that don't have primary keys when the cache is on (jeremyevans) (#213)
|
50
|
+
|
51
|
+
* Make Model#initialize, Model#set, and Model#update_with_params invulnerable to memory exhaustion (jeremyevans) (#210)
|
52
|
+
|
53
|
+
* Add Model.str_columns, which gives a list of columns as frozen strings (jeremyevans)
|
54
|
+
|
55
|
+
* Remove pretty_table.rb from sequel, since it is in sequel_core (jeremyevans)
|
56
|
+
|
1
57
|
=== 1.4.0 (2008-04-08)
|
2
58
|
|
3
59
|
* Don't mark a column as changed unless the new value is different from the current value (tamas.denes, jeremyevans) (#203).
|
data/README
CHANGED
@@ -1,10 +1,31 @@
|
|
1
|
-
== Sequel
|
1
|
+
== Sequel Models
|
2
2
|
|
3
|
-
Sequel
|
3
|
+
Models in Sequel are based on the Active Record pattern described by Martin Fowler (http://www.martinfowler.com/eaaCatalog/activeRecord.html). A model class corresponds to a table or a dataset, and an instance of that class wraps a single record in the model's underlying dataset.
|
4
4
|
|
5
|
-
|
5
|
+
Model classes are defined as regular Ruby classes:
|
6
6
|
|
7
|
-
|
7
|
+
DB = Sequel.connect('sqlite:/blog.db')
|
8
|
+
class Post < Sequel::Model
|
9
|
+
end
|
10
|
+
|
11
|
+
Just like in DataMapper or ActiveRecord, Sequel model classes assume that the table name is a plural of the class name:
|
12
|
+
|
13
|
+
Post.table_name #=> :posts
|
14
|
+
|
15
|
+
You can, however, explicitly set the table name or even the dataset used:
|
16
|
+
|
17
|
+
class Post < Sequel::Model(:my_posts)
|
18
|
+
end
|
19
|
+
|
20
|
+
# or:
|
21
|
+
|
22
|
+
Post.set_dataset :my_posts
|
23
|
+
|
24
|
+
# or:
|
25
|
+
|
26
|
+
Post.set_dataset DB[:my_posts].where(:category => 'ruby')
|
27
|
+
|
28
|
+
=== Resources
|
8
29
|
|
9
30
|
* {Project page}[http://code.google.com/p/ruby-sequel/]
|
10
31
|
* {Source code}[http://github.com/jeremyevans/sequel]
|
@@ -14,239 +35,321 @@ Sequel makes it easy to deal with multiple records without having to break your
|
|
14
35
|
* {API RDoc}[http://sequel.rubyforge.org]
|
15
36
|
|
16
37
|
To check out the source code:
|
17
|
-
|
38
|
+
|
18
39
|
git clone git://github.com/jeremyevans/sequel.git
|
19
|
-
|
40
|
+
|
20
41
|
=== Contact
|
21
42
|
|
22
43
|
If you have any comments or suggestions please post to the Google group.
|
23
44
|
|
24
|
-
|
45
|
+
=== Installation
|
25
46
|
|
26
47
|
sudo gem install sequel
|
27
|
-
|
28
|
-
== Supported Databases
|
29
48
|
|
30
|
-
|
49
|
+
=== Model instances
|
31
50
|
|
32
|
-
|
33
|
-
* DBI
|
34
|
-
* Informix
|
35
|
-
* MySQL
|
36
|
-
* ODBC
|
37
|
-
* Oracle
|
38
|
-
* PostgreSQL
|
39
|
-
* SQLite 3
|
51
|
+
Model instance are identified by a primary key. By default, Sequel assumes the primary key column to be :id. The Model#[] method can be used to fetch records by their primary key:
|
40
52
|
|
41
|
-
|
53
|
+
post = Post[123]
|
42
54
|
|
43
|
-
|
55
|
+
The Model#pk method is used to retrieve the record's primary key value:
|
44
56
|
|
45
|
-
|
57
|
+
post.pk #=> 123
|
46
58
|
|
47
|
-
|
59
|
+
Sequel models allow you to use any column as a primary key, and even composite keys made from multiple columns:
|
48
60
|
|
49
|
-
|
61
|
+
class Post < Sequel::Model
|
62
|
+
set_primary_key [:category, :title]
|
63
|
+
end
|
50
64
|
|
51
|
-
|
65
|
+
post = Post['ruby', 'hello world']
|
66
|
+
post.pk #=> ['ruby', 'hello world']
|
52
67
|
|
53
|
-
|
68
|
+
You can also define a model class that does not have a primary key, but then you lose the ability to update records.
|
54
69
|
|
55
|
-
|
70
|
+
A model instance can also be fetched by specifying a condition:
|
56
71
|
|
57
|
-
|
72
|
+
post = Post[:title => 'hello world']
|
73
|
+
post = Post.find{:num_comments < 10}
|
58
74
|
|
59
|
-
|
60
|
-
|
61
|
-
Which is equivalent to:
|
75
|
+
=== Iterating over records
|
62
76
|
|
63
|
-
|
77
|
+
A model class lets you iterate over specific records by acting as a proxy to the underlying dataset. This means that you can use the entire Dataset API to create customized queries that return model instances, e.g.:
|
64
78
|
|
65
|
-
|
79
|
+
Post.filter(:category => 'ruby').each{|post| p post}
|
66
80
|
|
67
|
-
|
68
|
-
middle_east.order(:name).each {|r| puts r[:name]}
|
69
|
-
|
70
|
-
Sequel also offers convenience methods for extracting data from Datasets, such as an extended map method:
|
81
|
+
You can also manipulate the records in the dataset:
|
71
82
|
|
72
|
-
|
73
|
-
|
74
|
-
Or getting results as a transposed hash, with one column as key and another as value:
|
83
|
+
Post.filter{:num_comments < 7}.delete
|
84
|
+
Post.filter{:title =~ /ruby/}.update(:category => 'ruby')
|
75
85
|
|
76
|
-
|
86
|
+
=== Accessing record values
|
77
87
|
|
78
|
-
|
88
|
+
A model instances stores its values as a hash:
|
79
89
|
|
80
|
-
|
90
|
+
post.values #=> {:id => 123, :category => 'ruby', :title => 'hello world'}
|
81
91
|
|
82
|
-
|
92
|
+
You can read the record values as object attributes (assuming the attribute names are valid columns in the model's dataset):
|
83
93
|
|
84
|
-
|
94
|
+
post.id #=> 123
|
95
|
+
post.title #=> 'hello world'
|
85
96
|
|
86
|
-
|
87
|
-
DB = Sequel.open 'sqlite:///blog.db'
|
88
|
-
|
89
|
-
The connection URL can also include such stuff as the user name and password:
|
97
|
+
You can also change record values:
|
90
98
|
|
91
|
-
|
99
|
+
post.title = 'hey there'
|
100
|
+
post.save
|
92
101
|
|
93
|
-
|
102
|
+
Another way to change values by using the #update_with_params method:
|
94
103
|
|
95
|
-
|
96
|
-
:max_connections => 10, :logger => Logger.new('log/db.log'))
|
104
|
+
post.update_with_params(:title => 'hey there')
|
97
105
|
|
98
|
-
===
|
106
|
+
=== Creating new records
|
99
107
|
|
100
|
-
|
101
|
-
DB.execute("insert into t values ('a', 'b')")
|
108
|
+
New records can be created by calling Model.create:
|
102
109
|
|
103
|
-
|
110
|
+
post = Post.create(:title => 'hello world')
|
104
111
|
|
105
|
-
|
106
|
-
DB << "insert into t values ('a', 'b')"
|
112
|
+
Another way is to construct a new instance and save it:
|
107
113
|
|
108
|
-
|
114
|
+
post = Post.new
|
115
|
+
post.title = 'hello world'
|
116
|
+
post.save
|
109
117
|
|
110
|
-
|
118
|
+
You can also supply a block to Model.new and Model.create:
|
111
119
|
|
112
|
-
|
120
|
+
post = Post.create {|p| p.title = 'hello world'}
|
113
121
|
|
114
|
-
|
122
|
+
post = Post.new do |p|
|
123
|
+
p.title = 'hello world'
|
124
|
+
p.save
|
125
|
+
end
|
115
126
|
|
116
|
-
|
127
|
+
=== Hooks
|
117
128
|
|
118
|
-
You can
|
129
|
+
You can execute custom code when creating, updating, or deleting records by using hooks. The before_create and after_create hooks wrap record creation. The before_update and after_update wrap record updating. The before_save and after_save wrap record creation and updating. The before_destroy and after_destroy wrap destruction.
|
119
130
|
|
120
|
-
|
131
|
+
Hooks are defined by supplying a block:
|
121
132
|
|
122
|
-
|
133
|
+
class Post < Sequel::Model
|
134
|
+
after_create do
|
135
|
+
self.created_at = Time.now
|
136
|
+
end
|
123
137
|
|
124
|
-
|
138
|
+
after_destroy do
|
139
|
+
author.update_post_count
|
140
|
+
end
|
141
|
+
end
|
125
142
|
|
126
|
-
|
143
|
+
=== Deleting records
|
127
144
|
|
128
|
-
|
145
|
+
You can delete individual records by calling #delete or #destroy. The only difference between the two methods is that #destroy invokes before_destroy and after_destroy hooks, while #delete does not:
|
129
146
|
|
130
|
-
|
147
|
+
post.delete #=> bypasses hooks
|
148
|
+
post.destroy #=> runs hooks
|
131
149
|
|
132
|
-
|
150
|
+
Records can also be deleted en-masse by invoking Model.delete and Model.destroy. As stated above, you can specify filters for the deleted records:
|
133
151
|
|
134
|
-
|
152
|
+
Post.filter(:category => 32).delete #=> bypasses hooks
|
153
|
+
Post.filter(:category => 32).destroy #=> runs hooks
|
135
154
|
|
136
|
-
|
155
|
+
Please note that if Model.destroy is called, each record is deleted
|
156
|
+
separately, but Model.delete deletes all relevant records with a single
|
157
|
+
SQL statement.
|
137
158
|
|
138
|
-
|
139
|
-
posts.inject({}) {|h, r| h[r[:id]] = r[:name]}
|
140
|
-
|
141
|
-
You can also retrieve the first record in a dataset:
|
159
|
+
=== Associations
|
142
160
|
|
143
|
-
|
144
|
-
|
145
|
-
Or retrieve a single record with a specific value:
|
161
|
+
Associations are used in order to specify relationships between model classes that reflect relations between tables in the database using foreign keys.
|
146
162
|
|
147
|
-
|
148
|
-
|
149
|
-
|
163
|
+
class Post < Sequel::Model
|
164
|
+
many_to_one :author
|
165
|
+
one_to_many :comments
|
166
|
+
many_to_many :tags
|
167
|
+
end
|
150
168
|
|
151
|
-
|
152
|
-
|
153
|
-
=== Filtering Records
|
169
|
+
You can also use the ActiveRecord names for these associations:
|
154
170
|
|
155
|
-
|
171
|
+
class Post < Sequel::Model
|
172
|
+
belongs_to :author
|
173
|
+
has_many :comments
|
174
|
+
has_and_belongs_to_many :tags
|
175
|
+
end
|
156
176
|
|
157
|
-
|
158
|
-
|
159
|
-
You can also specify ranges:
|
177
|
+
many_to_one/belongs_to creates a getter and setter for each model object:
|
160
178
|
|
161
|
-
|
162
|
-
|
163
|
-
|
179
|
+
class Post < Sequel::Model
|
180
|
+
many_to_one :author
|
181
|
+
end
|
164
182
|
|
165
|
-
|
166
|
-
|
167
|
-
|
183
|
+
post = Post.create(:name => 'hi!')
|
184
|
+
post.author = Author[:name => 'Sharon']
|
185
|
+
post.author
|
168
186
|
|
169
|
-
|
170
|
-
|
171
|
-
Which also lets you do stuff like:
|
187
|
+
one_to_many/has_many and many_to_many/has_and_belongs_to_many create a getter method, a method for adding an object to the association, and a method for removing an object from the association:
|
172
188
|
|
173
|
-
|
174
|
-
|
175
|
-
|
189
|
+
class Post < Sequel::Model
|
190
|
+
one_to_many :comments
|
191
|
+
many_to_many :tags
|
192
|
+
end
|
176
193
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
194
|
+
post = Post.create(:name => 'hi!')
|
195
|
+
post.comments
|
196
|
+
comment = Comment.create(:text=>'hi')
|
197
|
+
post.add_comment(comment)
|
198
|
+
post.remove_comment(comment)
|
199
|
+
tag = Tag.create(:tag=>'interesting')
|
200
|
+
post.add_tag(tag)
|
201
|
+
post.remove_tag(tag)
|
182
202
|
|
183
|
-
|
203
|
+
=== Eager Loading
|
184
204
|
|
185
|
-
|
186
|
-
|
187
|
-
You can also specify a custom WHERE clause:
|
205
|
+
Associations can be eagerly loaded via .eager and the :eager association option. Eager loading is used when loading a group of objects. It loads all associated objects for all of the current objects in one query, instead of using a separate query to get the associated objects for each current object. Eager loading requires that you retrieve all model objects at once via .all (instead of individually by .each). Eager loading can be cascaded, loading association's associated objects.
|
188
206
|
|
189
|
-
|
207
|
+
class Person < Sequel::Model
|
208
|
+
one_to_many :posts, :eager=>[:tags]
|
209
|
+
end
|
190
210
|
|
191
|
-
|
211
|
+
class Post < Sequel::Model
|
212
|
+
many_to_one :person
|
213
|
+
one_to_many :replies
|
214
|
+
many_to_many :tags
|
215
|
+
end
|
192
216
|
|
193
|
-
|
217
|
+
class Tag < Sequel::Model
|
218
|
+
many_to_many :posts
|
219
|
+
many_to_many :replies
|
220
|
+
end
|
194
221
|
|
195
|
-
|
222
|
+
class Reply < Sequel::Model
|
223
|
+
many_to_one :person
|
224
|
+
many_to_one :post
|
225
|
+
many_to_many :tags
|
226
|
+
end
|
196
227
|
|
197
|
-
|
198
|
-
|
228
|
+
# Eager loading via .eager
|
229
|
+
Post.eager(:person).all
|
199
230
|
|
200
|
-
|
201
|
-
|
231
|
+
# eager is a dataset method, so it works with filters/orders/limits/etc.
|
232
|
+
Post.filter("topic > 'M'").order(:date).limit(5).eager(:person).all
|
202
233
|
|
203
|
-
|
204
|
-
|
234
|
+
person = Person.first
|
235
|
+
# Eager loading via :eager (will eagerly load the tags for this person's posts)
|
236
|
+
person.posts
|
205
237
|
|
206
|
-
|
207
|
-
|
208
|
-
|
238
|
+
# These are equivalent
|
239
|
+
Post.eager(:person, :tags).all
|
240
|
+
Post.eager(:person).eager(:tags).all
|
209
241
|
|
210
|
-
|
242
|
+
# Cascading via .eager
|
243
|
+
Tag.eager(:posts=>:replies).all
|
244
|
+
|
245
|
+
# Will also grab all associated posts' tags (because of :eager)
|
246
|
+
Reply.eager(:person=>:posts).all
|
247
|
+
|
248
|
+
# No depth limit (other than memory/stack), and will also grab posts' tags
|
249
|
+
# Loads all people, their posts, their posts' tags, replies to those posts,
|
250
|
+
# the person for each reply, the tag for each reply, and all posts and
|
251
|
+
# replies that have that tag. Uses a total of 8 queries.
|
252
|
+
Person.eager(:posts=>{:replies=>[:person, {:tags=>{:posts, :replies}}]}).all
|
211
253
|
|
212
|
-
|
254
|
+
In addition to using eager, you can also use eager_graph, which will use a single query to get the object and all associated objects. This may be necessary if you want to filter the result set based on columns in associated tables. It works with cascading as well, the syntax is exactly the same. Note that using eager_graph to eagerly load multiple *_to_many associations will cause the result set to be a cartesian product, so you should be very careful with your filters when using it in that case.
|
213
255
|
|
214
|
-
===
|
256
|
+
=== Caching model instances with memcached
|
215
257
|
|
216
|
-
|
217
|
-
|
218
|
-
=== Inserting Records
|
258
|
+
Sequel models can be cached using memcached based on their primary keys. The use of memcached can significantly reduce database load by keeping model instances in memory. The set_cache method is used to specify caching:
|
219
259
|
|
220
|
-
|
221
|
-
|
222
|
-
Or alternatively:
|
260
|
+
require 'memcache'
|
261
|
+
CACHE = MemCache.new 'localhost:11211', :namespace => 'blog'
|
223
262
|
|
224
|
-
|
225
|
-
|
226
|
-
|
263
|
+
class Author < Sequel::Model
|
264
|
+
set_cache CACHE, :ttl => 3600
|
265
|
+
end
|
227
266
|
|
228
|
-
|
267
|
+
Author[333] # database hit
|
268
|
+
Author[333] # cache hit
|
229
269
|
|
230
|
-
===
|
270
|
+
=== Extending the underlying dataset
|
231
271
|
|
232
|
-
|
272
|
+
The obvious way to add table-wide logic is to define class methods to the model class definition. That way you can define subsets of the underlying dataset, change the ordering, or perform actions on multiple records:
|
233
273
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
274
|
+
class Post < Sequel::Model
|
275
|
+
def self.posts_with_few_comments
|
276
|
+
filter{:num_comments < 30}
|
277
|
+
end
|
238
278
|
|
239
|
-
|
240
|
-
|
241
|
-
|
279
|
+
def self.clean_posts_with_few_comments
|
280
|
+
posts_with_few_comments.delete
|
281
|
+
end
|
282
|
+
end
|
242
283
|
|
243
|
-
You can
|
284
|
+
You can also implement table-wide logic by defining methods on the dataset:
|
244
285
|
|
245
|
-
|
246
|
-
|
247
|
-
|
286
|
+
class Post < Sequel::Model
|
287
|
+
def_dataset_method(:posts_with_few_comments) do
|
288
|
+
filter{:num_comments < 30}
|
289
|
+
end
|
248
290
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
291
|
+
def_dataset_method(:clean_posts_with_few_comments) do
|
292
|
+
posts_with_few_comments.delete
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
This is the recommended way of implementing table-wide operations, and allows you to have access to your model API from filtered datasets as well:
|
297
|
+
|
298
|
+
Post.filter(:category => 'ruby').clean_old_posts
|
299
|
+
|
300
|
+
Sequel models also provide a short hand notation for filters:
|
301
|
+
|
302
|
+
class Post < Sequel::Model
|
303
|
+
subset(:posts_with_few_comments){:num_comments < 30}
|
304
|
+
subset :invisible, :visible => false
|
305
|
+
end
|
306
|
+
|
307
|
+
=== Defining the underlying schema
|
308
|
+
|
309
|
+
Model classes can also be used as a place to define your table schema and control it. The schema DSL is exactly the same provided by Sequel::Schema::Generator:
|
310
|
+
|
311
|
+
class Post < Sequel::Model
|
312
|
+
set_schema do
|
313
|
+
primary_key :id
|
314
|
+
text :title
|
315
|
+
text :category
|
316
|
+
foreign_key :author_id, :table => :authors
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
You can then create the underlying table, drop it, or recreate it:
|
321
|
+
|
322
|
+
Post.table_exists?
|
323
|
+
Post.create_table
|
324
|
+
Post.drop_table
|
325
|
+
Post.create_table! # drops the table if it exists and then recreates it
|
326
|
+
|
327
|
+
=== Basic Model Validations
|
328
|
+
|
329
|
+
To assign default validations to a sequel model:
|
330
|
+
|
331
|
+
class MyModel < Sequel::Model
|
332
|
+
validates do
|
333
|
+
format_of...
|
334
|
+
presence_of...
|
335
|
+
acceptance_of...
|
336
|
+
confirmation_of...
|
337
|
+
length_of...
|
338
|
+
numericality_of...
|
339
|
+
format_of...
|
340
|
+
each...
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
You may also perform the usual 'longhand' way to assign default model validates directly within the model class itself:
|
345
|
+
|
346
|
+
class MyModel < Sequel::Model
|
347
|
+
validates_format_of...
|
348
|
+
validates_presence_of...
|
349
|
+
validates_acceptance_of...
|
350
|
+
validates_confirmation_of...
|
351
|
+
validates_length_of...
|
352
|
+
validates_numericality_of...
|
353
|
+
validates_format_of...
|
354
|
+
validates_each...
|
355
|
+
end
|