Empact-sexy_pg_constraints 0.2.0
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.rdoc +12 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +37 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +123 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/init.rb +1 -0
- data/lib/sexy_pg_constraints.rb +23 -0
- data/lib/sexy_pg_constraints/constrainer.rb +34 -0
- data/lib/sexy_pg_constraints/constraints.rb +179 -0
- data/lib/sexy_pg_constraints/deconstrainer.rb +31 -0
- data/lib/sexy_pg_constraints/helpers.rb +19 -0
- data/lib/sexy_pg_constraints/initializer.rb +7 -0
- data/sexy_pg_constraints.gemspec +32 -0
- data/test/sexy_pg_constraints_test.rb +899 -0
- data/test/support/assert_prohibits_allows.rb +28 -0
- data/test/support/database.yml.example +6 -0
- data/test/support/models.rb +36 -0
- data/test/test_helper.rb +27 -0
- metadata +146 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
module SexyPgConstraints
|
2
|
+
class DeConstrainer
|
3
|
+
include SexyPgConstraints::Helpers
|
4
|
+
|
5
|
+
def initialize(table, columns = [])
|
6
|
+
@table = table.to_s
|
7
|
+
@columns = columns
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing(column, *constraints)
|
11
|
+
self.class.drop_constraints(@table, column.to_s, *constraints)
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](*columns)
|
15
|
+
@columns = columns.map{|c| c.to_s}
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def all(*constraints)
|
20
|
+
self.class.drop_constraints(@table, @columns, *constraints)
|
21
|
+
end
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def drop_constraints(table, column, *constraints)
|
25
|
+
constraints.each do |type|
|
26
|
+
execute "alter table #{table} drop constraint #{make_title(table, column, type)};"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SexyPgConstraints
|
2
|
+
module Helpers
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def make_title(table, column, type)
|
9
|
+
column = column.join('_') if column.respond_to?(:join)
|
10
|
+
|
11
|
+
"#{table}_#{column}_#{type}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute(*args)
|
15
|
+
ActiveRecord::Base.connection.execute(*args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{sexy_pg_constraints}
|
5
|
+
s.version = "0.1.3"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Maxim Chernyak"]
|
9
|
+
s.date = %q{2009-01-19}
|
10
|
+
s.description = %q{Use migrations and simple syntax to manage constraints in PostgreSQL DB.}
|
11
|
+
s.email = %q{max@bitsonnet.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG.rdoc", "lib/constrainer.rb", "lib/constraints.rb", "lib/deconstrainer.rb", "lib/helpers.rb", "lib/sexy_pg_constraints.rb", "README.rdoc"]
|
13
|
+
s.files = ["CHANGELOG.rdoc", "init.rb", "lib/constrainer.rb", "lib/constraints.rb", "lib/deconstrainer.rb", "lib/helpers.rb", "lib/sexy_pg_constraints.rb", "Manifest", "Rakefile", "README.rdoc", "sexy_pg_constraints.gemspec", "test/postgresql_adapter.rb", "test/sexy_pg_constraints_test.rb", "test/test_helper.rb"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/maxim/sexy_pg_constraints}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Sexy_pg_constraints", "--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{sexy_pg_constraints}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{Use migrations and simple syntax to manage constraints in PostgreSQL DB.}
|
21
|
+
s.test_files = ["test/sexy_pg_constraints_test.rb", "test/test_helper.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,899 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SexyPgConstraintsTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
CreateBooks.up
|
6
|
+
CreateAuthors.up
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
CreateBooks.down
|
11
|
+
CreateAuthors.down
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_create_book
|
15
|
+
Book.create
|
16
|
+
assert_equal 1, Book.count
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_whitelist
|
20
|
+
ActiveRecord::Migration.constrain :books, :author, :whitelist => %w(whitelisted1 whitelisted2 whitelisted3)
|
21
|
+
|
22
|
+
assert_prohibits Book, :author, :whitelist do |book|
|
23
|
+
book.author = 'not_whitelisted'
|
24
|
+
end
|
25
|
+
|
26
|
+
assert_allows Book do |book|
|
27
|
+
book.author = 'whitelisted2'
|
28
|
+
end
|
29
|
+
|
30
|
+
ActiveRecord::Migration.deconstrain :books, :author, :whitelist
|
31
|
+
|
32
|
+
assert_allows Book do |book|
|
33
|
+
book.author = 'not_whitelisted'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_whitelist_on_a_column_whose_name_is_a_sql_keyword
|
38
|
+
ActiveRecord::Migration.constrain :books, :as, :whitelist => %w(whitelisted1 whitelisted2 whitelisted3)
|
39
|
+
|
40
|
+
assert_prohibits Book, :as, :whitelist do |book|
|
41
|
+
book.as = 'not_whitelisted'
|
42
|
+
end
|
43
|
+
|
44
|
+
assert_allows Book do |book|
|
45
|
+
book.as = 'whitelisted2'
|
46
|
+
end
|
47
|
+
|
48
|
+
ActiveRecord::Migration.deconstrain :books, :as, :whitelist
|
49
|
+
|
50
|
+
assert_allows Book do |book|
|
51
|
+
book.as = 'not_whitelisted'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_blacklist
|
56
|
+
ActiveRecord::Migration.constrain :books, :author, :blacklist => %w(blacklisted1 blacklisted2 blacklisted3)
|
57
|
+
|
58
|
+
assert_prohibits Book, :author, :blacklist do |book|
|
59
|
+
book.author = 'blacklisted2'
|
60
|
+
end
|
61
|
+
|
62
|
+
assert_allows Book do |book|
|
63
|
+
book.author = 'not_blacklisted'
|
64
|
+
end
|
65
|
+
|
66
|
+
ActiveRecord::Migration.deconstrain :books, :author, :blacklist
|
67
|
+
|
68
|
+
assert_allows Book do |book|
|
69
|
+
book.author = 'blacklisted2'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_blacklist_on_a_column_whose_name_is_a_sql_keyword
|
74
|
+
ActiveRecord::Migration.constrain :books, :as, :blacklist => %w(blacklisted1 blacklisted2 blacklisted3)
|
75
|
+
|
76
|
+
assert_prohibits Book, :as, :blacklist do |book|
|
77
|
+
book.as = 'blacklisted2'
|
78
|
+
end
|
79
|
+
|
80
|
+
assert_allows Book do |book|
|
81
|
+
book.as = 'not_blacklisted'
|
82
|
+
end
|
83
|
+
|
84
|
+
ActiveRecord::Migration.deconstrain :books, :as, :blacklist
|
85
|
+
|
86
|
+
assert_allows Book do |book|
|
87
|
+
book.as = 'blacklisted2'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_not_blank
|
92
|
+
ActiveRecord::Migration.constrain :books, :author, :not_blank => true
|
93
|
+
|
94
|
+
assert_prohibits Book, :author, :not_blank do |book|
|
95
|
+
book.author = ' '
|
96
|
+
end
|
97
|
+
|
98
|
+
assert_allows Book do |book|
|
99
|
+
book.author = 'foo'
|
100
|
+
end
|
101
|
+
|
102
|
+
ActiveRecord::Migration.deconstrain :books, :author, :not_blank
|
103
|
+
|
104
|
+
assert_allows Book do |book|
|
105
|
+
book.author = ' '
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_not_blank_on_a_column_whose_name_is_a_sql_keyword
|
110
|
+
ActiveRecord::Migration.constrain :books, :as, :not_blank => true
|
111
|
+
|
112
|
+
assert_prohibits Book, :as, :not_blank do |book|
|
113
|
+
book.as = ' '
|
114
|
+
end
|
115
|
+
|
116
|
+
assert_allows Book do |book|
|
117
|
+
book.as = 'foo'
|
118
|
+
end
|
119
|
+
|
120
|
+
ActiveRecord::Migration.deconstrain :books, :as, :not_blank
|
121
|
+
|
122
|
+
assert_allows Book do |book|
|
123
|
+
book.as = ' '
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_within_inclusive
|
128
|
+
ActiveRecord::Migration.constrain :books, :quantity, :within => 5..11
|
129
|
+
|
130
|
+
assert_prohibits Book, :quantity, :within do |book|
|
131
|
+
book.quantity = 12
|
132
|
+
end
|
133
|
+
|
134
|
+
assert_prohibits Book, :quantity, :within do |book|
|
135
|
+
book.quantity = 4
|
136
|
+
end
|
137
|
+
|
138
|
+
assert_allows Book do |book|
|
139
|
+
book.quantity = 7
|
140
|
+
end
|
141
|
+
|
142
|
+
ActiveRecord::Migration.deconstrain :books, :quantity, :within
|
143
|
+
|
144
|
+
assert_allows Book do |book|
|
145
|
+
book.quantity = 12
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_within_inclusive_on_a_column_whose_name_is_a_sql_keyword
|
150
|
+
ActiveRecord::Migration.constrain :books, :from, :within => 5..11
|
151
|
+
|
152
|
+
assert_prohibits Book, :from, :within do |book|
|
153
|
+
book.from = 12
|
154
|
+
end
|
155
|
+
|
156
|
+
assert_prohibits Book, :from, :within do |book|
|
157
|
+
book.from = 4
|
158
|
+
end
|
159
|
+
|
160
|
+
assert_allows Book do |book|
|
161
|
+
book.from = 7
|
162
|
+
end
|
163
|
+
|
164
|
+
ActiveRecord::Migration.deconstrain :books, :from, :within
|
165
|
+
|
166
|
+
assert_allows Book do |book|
|
167
|
+
book.from = 12
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_within_non_inclusive
|
172
|
+
ActiveRecord::Migration.constrain :books, :quantity, :within => 5...11
|
173
|
+
|
174
|
+
assert_prohibits Book, :quantity, :within do |book|
|
175
|
+
book.quantity = 11
|
176
|
+
end
|
177
|
+
|
178
|
+
assert_prohibits Book, :quantity, :within do |book|
|
179
|
+
book.quantity = 4
|
180
|
+
end
|
181
|
+
|
182
|
+
assert_allows Book do |book|
|
183
|
+
book.quantity = 10
|
184
|
+
end
|
185
|
+
|
186
|
+
ActiveRecord::Migration.deconstrain :books, :quantity, :within
|
187
|
+
|
188
|
+
assert_allows Book do |book|
|
189
|
+
book.quantity = 11
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_within_non_inclusive_on_a_column_whose_name_is_a_sql_keyword
|
194
|
+
ActiveRecord::Migration.constrain :books, :from, :within => 5...11
|
195
|
+
|
196
|
+
assert_prohibits Book, :from, :within do |book|
|
197
|
+
book.from = 11
|
198
|
+
end
|
199
|
+
|
200
|
+
assert_prohibits Book, :from, :within do |book|
|
201
|
+
book.from = 4
|
202
|
+
end
|
203
|
+
|
204
|
+
assert_allows Book do |book|
|
205
|
+
book.from = 10
|
206
|
+
end
|
207
|
+
|
208
|
+
ActiveRecord::Migration.deconstrain :books, :from, :within
|
209
|
+
|
210
|
+
assert_allows Book do |book|
|
211
|
+
book.from = 11
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_length_within_inclusive
|
216
|
+
ActiveRecord::Migration.constrain :books, :title, :length_within => 5..11
|
217
|
+
|
218
|
+
assert_prohibits Book, :title, :length_within do |book|
|
219
|
+
book.title = 'abcdefghijkl'
|
220
|
+
end
|
221
|
+
|
222
|
+
assert_prohibits Book, :title, :length_within do |book|
|
223
|
+
book.title = 'abcd'
|
224
|
+
end
|
225
|
+
|
226
|
+
assert_allows Book do |book|
|
227
|
+
book.title = 'abcdefg'
|
228
|
+
end
|
229
|
+
|
230
|
+
ActiveRecord::Migration.deconstrain :books, :title, :length_within
|
231
|
+
|
232
|
+
assert_allows Book do |book|
|
233
|
+
book.title = 'abcdefghijkl'
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_length_within_inclusive_on_a_column_whose_name_is_a_sql_keyword
|
238
|
+
ActiveRecord::Migration.constrain :books, :as, :length_within => 5..11
|
239
|
+
|
240
|
+
assert_prohibits Book, :as, :length_within do |book|
|
241
|
+
book.as = 'abcdefghijkl'
|
242
|
+
end
|
243
|
+
|
244
|
+
assert_prohibits Book, :as, :length_within do |book|
|
245
|
+
book.as = 'abcd'
|
246
|
+
end
|
247
|
+
|
248
|
+
assert_allows Book do |book|
|
249
|
+
book.as = 'abcdefg'
|
250
|
+
end
|
251
|
+
|
252
|
+
ActiveRecord::Migration.deconstrain :books, :as, :length_within
|
253
|
+
|
254
|
+
assert_allows Book do |book|
|
255
|
+
book.as = 'abcdefghijkl'
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_length_within_non_inclusive
|
260
|
+
ActiveRecord::Migration.constrain :books, :title, :length_within => 5...11
|
261
|
+
|
262
|
+
assert_prohibits Book, :title, :length_within do |book|
|
263
|
+
book.title = 'abcdefghijk'
|
264
|
+
end
|
265
|
+
|
266
|
+
assert_prohibits Book, :title, :length_within do |book|
|
267
|
+
book.title = 'abcd'
|
268
|
+
end
|
269
|
+
|
270
|
+
assert_allows Book do |book|
|
271
|
+
book.title = 'abcdefg'
|
272
|
+
end
|
273
|
+
|
274
|
+
ActiveRecord::Migration.deconstrain :books, :title, :length_within
|
275
|
+
|
276
|
+
assert_allows Book do |book|
|
277
|
+
book.title = 'abcdefghijk'
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def test_length_within_non_inclusive_on_a_column_whose_name_is_a_sql_keyword
|
282
|
+
ActiveRecord::Migration.constrain :books, :as, :length_within => 5...11
|
283
|
+
|
284
|
+
assert_prohibits Book, :as, :length_within do |book|
|
285
|
+
book.as = 'abcdefghijk'
|
286
|
+
end
|
287
|
+
|
288
|
+
assert_prohibits Book, :as, :length_within do |book|
|
289
|
+
book.as = 'abcd'
|
290
|
+
end
|
291
|
+
|
292
|
+
assert_allows Book do |book|
|
293
|
+
book.as = 'abcdefg'
|
294
|
+
end
|
295
|
+
|
296
|
+
ActiveRecord::Migration.deconstrain :books, :as, :length_within
|
297
|
+
|
298
|
+
assert_allows Book do |book|
|
299
|
+
book.as = 'abcdefghijk'
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def test_email
|
304
|
+
ActiveRecord::Migration.constrain :books, :author, :email => true
|
305
|
+
|
306
|
+
assert_prohibits Book, :author, :email do |book|
|
307
|
+
book.author = 'blah@example'
|
308
|
+
end
|
309
|
+
|
310
|
+
assert_allows Book do |book|
|
311
|
+
book.author = 'blah@example.com'
|
312
|
+
end
|
313
|
+
|
314
|
+
ActiveRecord::Migration.deconstrain :books, :author, :email
|
315
|
+
|
316
|
+
assert_allows Book do |book|
|
317
|
+
book.author = 'blah@example'
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def test_email_on_a_column_whose_name_is_a_sql_keyword
|
322
|
+
ActiveRecord::Migration.constrain :books, :as, :email => true
|
323
|
+
|
324
|
+
assert_prohibits Book, :as, :email do |book|
|
325
|
+
book.as = 'blah@example'
|
326
|
+
end
|
327
|
+
|
328
|
+
assert_allows Book do |book|
|
329
|
+
book.as = 'blah@example.com'
|
330
|
+
end
|
331
|
+
|
332
|
+
ActiveRecord::Migration.deconstrain :books, :as, :email
|
333
|
+
|
334
|
+
assert_allows Book do |book|
|
335
|
+
book.as = 'blah@example'
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def test_alphanumeric
|
340
|
+
ActiveRecord::Migration.constrain :books, :title, :alphanumeric => true
|
341
|
+
|
342
|
+
assert_prohibits Book, :title, :alphanumeric do |book|
|
343
|
+
book.title = 'asdf@asdf'
|
344
|
+
end
|
345
|
+
|
346
|
+
assert_allows Book do |book|
|
347
|
+
book.title = 'asdf'
|
348
|
+
end
|
349
|
+
|
350
|
+
ActiveRecord::Migration.deconstrain :books, :title, :alphanumeric
|
351
|
+
|
352
|
+
assert_allows Book do |book|
|
353
|
+
book.title = 'asdf@asdf'
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def test_alphanumeric_on_a_column_whose_name_is_a_sql_keyword
|
358
|
+
ActiveRecord::Migration.constrain :books, :as, :alphanumeric => true
|
359
|
+
|
360
|
+
assert_prohibits Book, :as, :alphanumeric do |book|
|
361
|
+
book.as = 'asdf@asdf'
|
362
|
+
end
|
363
|
+
|
364
|
+
assert_allows Book do |book|
|
365
|
+
book.as = 'asdf'
|
366
|
+
end
|
367
|
+
|
368
|
+
ActiveRecord::Migration.deconstrain :books, :as, :alphanumeric
|
369
|
+
|
370
|
+
assert_allows Book do |book|
|
371
|
+
book.as = 'asdf@asdf'
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_positive
|
376
|
+
ActiveRecord::Migration.constrain :books, :quantity, :positive => true
|
377
|
+
|
378
|
+
assert_prohibits Book, :quantity, :positive do |book|
|
379
|
+
book.quantity = -1
|
380
|
+
end
|
381
|
+
|
382
|
+
assert_allows Book do |book|
|
383
|
+
book.quantity = 0
|
384
|
+
end
|
385
|
+
|
386
|
+
assert_allows Book do |book|
|
387
|
+
book.quantity = 1
|
388
|
+
end
|
389
|
+
|
390
|
+
ActiveRecord::Migration.deconstrain :books, :quantity, :positive
|
391
|
+
|
392
|
+
assert_allows Book do |book|
|
393
|
+
book.quantity = -1
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
def test_positive_on_a_column_whose_name_is_a_sql_keyword
|
398
|
+
ActiveRecord::Migration.constrain :books, :from, :positive => true
|
399
|
+
|
400
|
+
assert_prohibits Book, :from, :positive do |book|
|
401
|
+
book.from = -1
|
402
|
+
end
|
403
|
+
|
404
|
+
assert_allows Book do |book|
|
405
|
+
book.from = 0
|
406
|
+
end
|
407
|
+
|
408
|
+
assert_allows Book do |book|
|
409
|
+
book.from = 1
|
410
|
+
end
|
411
|
+
|
412
|
+
ActiveRecord::Migration.deconstrain :books, :from, :positive
|
413
|
+
|
414
|
+
assert_allows Book do |book|
|
415
|
+
book.from = -1
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
def test_odd
|
420
|
+
ActiveRecord::Migration.constrain :books, :quantity, :odd => true
|
421
|
+
|
422
|
+
assert_prohibits Book, :quantity, :odd do |book|
|
423
|
+
book.quantity = 2
|
424
|
+
end
|
425
|
+
|
426
|
+
assert_allows Book do |book|
|
427
|
+
book.quantity = 1
|
428
|
+
end
|
429
|
+
|
430
|
+
ActiveRecord::Migration.deconstrain :books, :quantity, :odd
|
431
|
+
|
432
|
+
assert_allows Book do |book|
|
433
|
+
book.quantity = 2
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
def test_odd_on_a_column_whose_name_is_a_sql_keyword
|
438
|
+
ActiveRecord::Migration.constrain :books, :from, :odd => true
|
439
|
+
|
440
|
+
assert_prohibits Book, :from, :odd do |book|
|
441
|
+
book.from = 2
|
442
|
+
end
|
443
|
+
|
444
|
+
assert_allows Book do |book|
|
445
|
+
book.from = 1
|
446
|
+
end
|
447
|
+
|
448
|
+
ActiveRecord::Migration.deconstrain :books, :from, :odd
|
449
|
+
|
450
|
+
assert_allows Book do |book|
|
451
|
+
book.from = 2
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
def test_even
|
456
|
+
ActiveRecord::Migration.constrain :books, :quantity, :even => true
|
457
|
+
|
458
|
+
assert_prohibits Book, :quantity, :even do |book|
|
459
|
+
book.quantity = 1
|
460
|
+
end
|
461
|
+
|
462
|
+
assert_allows Book do |book|
|
463
|
+
book.quantity = 2
|
464
|
+
end
|
465
|
+
|
466
|
+
ActiveRecord::Migration.deconstrain :books, :quantity, :even
|
467
|
+
|
468
|
+
assert_allows Book do |book|
|
469
|
+
book.quantity = 1
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
def test_even_on_a_column_whose_name_is_a_sql_keyword
|
474
|
+
ActiveRecord::Migration.constrain :books, :from, :even => true
|
475
|
+
|
476
|
+
assert_prohibits Book, :from, :even do |book|
|
477
|
+
book.from = 1
|
478
|
+
end
|
479
|
+
|
480
|
+
assert_allows Book do |book|
|
481
|
+
book.from = 2
|
482
|
+
end
|
483
|
+
|
484
|
+
ActiveRecord::Migration.deconstrain :books, :from, :even
|
485
|
+
|
486
|
+
assert_allows Book do |book|
|
487
|
+
book.from = 1
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
def test_unique
|
492
|
+
ActiveRecord::Migration.constrain :books, :isbn, :unique => true
|
493
|
+
|
494
|
+
assert_allows Book do |book|
|
495
|
+
book.isbn = 'foo'
|
496
|
+
end
|
497
|
+
|
498
|
+
assert_prohibits Book, :isbn, :unique, 'unique', ActiveRecord::RecordNotUnique do |book|
|
499
|
+
book.isbn = 'foo'
|
500
|
+
end
|
501
|
+
|
502
|
+
ActiveRecord::Migration.deconstrain :books, :isbn, :unique
|
503
|
+
|
504
|
+
assert_allows Book do |book|
|
505
|
+
book.isbn = 'foo'
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
def test_unique_on_a_column_whose_name_is_a_sql_keyword
|
510
|
+
ActiveRecord::Migration.constrain :books, :as, :unique => true
|
511
|
+
|
512
|
+
assert_allows Book do |book|
|
513
|
+
book.as = 'foo'
|
514
|
+
end
|
515
|
+
|
516
|
+
assert_prohibits Book, :as, :unique, 'unique', ActiveRecord::RecordNotUnique do |book|
|
517
|
+
book.as = 'foo'
|
518
|
+
end
|
519
|
+
|
520
|
+
ActiveRecord::Migration.deconstrain :books, :as, :unique
|
521
|
+
|
522
|
+
assert_allows Book do |book|
|
523
|
+
book.as = 'foo'
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
def test_exact_length
|
528
|
+
ActiveRecord::Migration.constrain :books, :isbn, :exact_length => 5
|
529
|
+
|
530
|
+
assert_prohibits Book, :isbn, :exact_length do |book|
|
531
|
+
book.isbn = '123456'
|
532
|
+
end
|
533
|
+
|
534
|
+
assert_prohibits Book, :isbn, :exact_length do |book|
|
535
|
+
book.isbn = '1234'
|
536
|
+
end
|
537
|
+
|
538
|
+
assert_allows Book do |book|
|
539
|
+
book.isbn = '12345'
|
540
|
+
end
|
541
|
+
|
542
|
+
ActiveRecord::Migration.deconstrain :books, :isbn, :exact_length
|
543
|
+
|
544
|
+
assert_allows Book do |book|
|
545
|
+
book.isbn = '123456'
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
def test_exact_length_on_a_column_whose_name_is_a_sql_keyword
|
550
|
+
ActiveRecord::Migration.constrain :books, :as, :exact_length => 5
|
551
|
+
|
552
|
+
assert_prohibits Book, :as, :exact_length do |book|
|
553
|
+
book.as = '123456'
|
554
|
+
end
|
555
|
+
|
556
|
+
assert_prohibits Book, :as, :exact_length do |book|
|
557
|
+
book.as = '1234'
|
558
|
+
end
|
559
|
+
|
560
|
+
assert_allows Book do |book|
|
561
|
+
book.as = '12345'
|
562
|
+
end
|
563
|
+
|
564
|
+
ActiveRecord::Migration.deconstrain :books, :as, :exact_length
|
565
|
+
|
566
|
+
assert_allows Book do |book|
|
567
|
+
book.as = '123456'
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
def test_format_case_insensitive
|
572
|
+
ActiveRecord::Migration.constrain :books, :title, :format => /^[a-z]+$/i
|
573
|
+
|
574
|
+
assert_prohibits Book, :title, :format do |book|
|
575
|
+
book.title = 'abc3'
|
576
|
+
end
|
577
|
+
|
578
|
+
assert_prohibits Book, :title, :format do |book|
|
579
|
+
book.title = ''
|
580
|
+
end
|
581
|
+
|
582
|
+
assert_allows Book do |book|
|
583
|
+
book.title = 'abc'
|
584
|
+
end
|
585
|
+
|
586
|
+
assert_allows Book do |book|
|
587
|
+
book.title = 'ABc'
|
588
|
+
end
|
589
|
+
|
590
|
+
ActiveRecord::Migration.deconstrain :books, :title, :format
|
591
|
+
|
592
|
+
assert_allows Book do |book|
|
593
|
+
book.title = 'abc3'
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
def test_format_case_insensitive_on_a_column_whose_name_is_a_sql_keyword
|
598
|
+
ActiveRecord::Migration.constrain :books, :as, :format => /^[a-z]+$/i
|
599
|
+
|
600
|
+
assert_prohibits Book, :as, :format do |book|
|
601
|
+
book.as = 'abc3'
|
602
|
+
end
|
603
|
+
|
604
|
+
assert_prohibits Book, :as, :format do |book|
|
605
|
+
book.as = ''
|
606
|
+
end
|
607
|
+
|
608
|
+
assert_allows Book do |book|
|
609
|
+
book.as = 'abc'
|
610
|
+
end
|
611
|
+
|
612
|
+
assert_allows Book do |book|
|
613
|
+
book.as = 'ABc'
|
614
|
+
end
|
615
|
+
|
616
|
+
ActiveRecord::Migration.deconstrain :books, :as, :format
|
617
|
+
|
618
|
+
assert_allows Book do |book|
|
619
|
+
book.as = 'abc3'
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
def test_format_case_sensitive
|
624
|
+
ActiveRecord::Migration.constrain :books, :title, :format => /^[a-z]+$/
|
625
|
+
|
626
|
+
assert_prohibits Book, :title, :format do |book|
|
627
|
+
book.title = 'aBc'
|
628
|
+
end
|
629
|
+
|
630
|
+
assert_allows Book do |book|
|
631
|
+
book.title = 'abc'
|
632
|
+
end
|
633
|
+
|
634
|
+
ActiveRecord::Migration.deconstrain :books, :title, :format
|
635
|
+
|
636
|
+
assert_allows Book do |book|
|
637
|
+
book.title = 'aBc'
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
641
|
+
def test_format_case_sensitive_on_a_column_whose_name_is_a_sql_keyword
|
642
|
+
ActiveRecord::Migration.constrain :books, :as, :format => /^[a-z]+$/
|
643
|
+
|
644
|
+
assert_prohibits Book, :as, :format do |book|
|
645
|
+
book.as = 'aBc'
|
646
|
+
end
|
647
|
+
|
648
|
+
assert_allows Book do |book|
|
649
|
+
book.as = 'abc'
|
650
|
+
end
|
651
|
+
|
652
|
+
ActiveRecord::Migration.deconstrain :books, :as, :format
|
653
|
+
|
654
|
+
assert_allows Book do |book|
|
655
|
+
book.as = 'aBc'
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
def test_reference
|
660
|
+
ActiveRecord::Migration.constrain :books, :author_id, :reference => {:authors => :id}
|
661
|
+
|
662
|
+
assert_prohibits Book, :author_id, :reference, 'foreign key', ActiveRecord::InvalidForeignKey do |book|
|
663
|
+
book.author_id = 1
|
664
|
+
end
|
665
|
+
|
666
|
+
author = Author.new
|
667
|
+
author.name = "Mark Twain"
|
668
|
+
author.bio = "American writer"
|
669
|
+
assert author.save
|
670
|
+
|
671
|
+
assert_equal 1, author.id
|
672
|
+
|
673
|
+
assert_allows Book do |book|
|
674
|
+
book.author_id = 1
|
675
|
+
end
|
676
|
+
|
677
|
+
ActiveRecord::Migration.deconstrain :books, :author_id, :reference
|
678
|
+
|
679
|
+
assert_allows Book do |book|
|
680
|
+
book.author_id = 2
|
681
|
+
end
|
682
|
+
end
|
683
|
+
|
684
|
+
def test_reference_on_a_column_whose_name_is_a_sql_keyword
|
685
|
+
ActiveRecord::Migration.constrain :books, :from, :reference => {:authors => :id}
|
686
|
+
|
687
|
+
assert_prohibits Book, :from, :reference, 'foreign key', ActiveRecord::InvalidForeignKey do |book|
|
688
|
+
book.from = 1
|
689
|
+
end
|
690
|
+
|
691
|
+
author = Author.new
|
692
|
+
author.name = "Mark Twain"
|
693
|
+
author.bio = "American writer"
|
694
|
+
assert author.save
|
695
|
+
|
696
|
+
assert_equal 1, author.id
|
697
|
+
|
698
|
+
assert_allows Book do |book|
|
699
|
+
book.from = 1
|
700
|
+
end
|
701
|
+
|
702
|
+
ActiveRecord::Migration.deconstrain :books, :from, :reference
|
703
|
+
|
704
|
+
assert_allows Book do |book|
|
705
|
+
book.from = 2
|
706
|
+
end
|
707
|
+
end
|
708
|
+
|
709
|
+
def test_reference_with_on_delete
|
710
|
+
ActiveRecord::Migration.constrain :books, :author_id, :reference => {:authors => :id, :on_delete => :cascade}
|
711
|
+
|
712
|
+
author = Author.new
|
713
|
+
author.name = "Mark Twain"
|
714
|
+
author.bio = "American writer"
|
715
|
+
assert author.save
|
716
|
+
|
717
|
+
assert_equal 1, Author.count
|
718
|
+
|
719
|
+
assert_allows Book do |book|
|
720
|
+
book.title = "The Adventures of Tom Sawyer"
|
721
|
+
book.author_id = 1
|
722
|
+
end
|
723
|
+
|
724
|
+
assert_allows Book do |book|
|
725
|
+
book.title = "The Adventures of Huckleberry Finn"
|
726
|
+
book.author_id = 1
|
727
|
+
end
|
728
|
+
|
729
|
+
author.destroy
|
730
|
+
|
731
|
+
assert_equal 0, Author.count
|
732
|
+
assert_equal 0, Book.count
|
733
|
+
end
|
734
|
+
|
735
|
+
def test_block_syntax
|
736
|
+
ActiveRecord::Migration.constrain :books do |t|
|
737
|
+
t.title :not_blank => true
|
738
|
+
t.isbn :exact_length => 15
|
739
|
+
t.author :alphanumeric => true
|
740
|
+
end
|
741
|
+
|
742
|
+
assert_prohibits Book, :title, :not_blank do |book|
|
743
|
+
book.title = ' '
|
744
|
+
end
|
745
|
+
|
746
|
+
assert_prohibits Book, :isbn, :exact_length do |book|
|
747
|
+
book.isbn = 'asdf'
|
748
|
+
end
|
749
|
+
|
750
|
+
assert_prohibits Book, :author, :alphanumeric do |book|
|
751
|
+
book.author = 'foo#bar'
|
752
|
+
end
|
753
|
+
|
754
|
+
ActiveRecord::Migration.deconstrain :books do |t|
|
755
|
+
t.title :not_blank
|
756
|
+
t.isbn :exact_length
|
757
|
+
t.author :alphanumeric
|
758
|
+
end
|
759
|
+
|
760
|
+
assert_allows Book do |book|
|
761
|
+
book.title = ' '
|
762
|
+
book.isbn = 'asdf'
|
763
|
+
book.author = 'foo#bar'
|
764
|
+
end
|
765
|
+
end
|
766
|
+
|
767
|
+
def test_multiple_constraints_per_line
|
768
|
+
ActiveRecord::Migration.constrain :books do |t|
|
769
|
+
t.title :not_blank => true, :alphanumeric => true, :blacklist => %w(foo bar)
|
770
|
+
end
|
771
|
+
|
772
|
+
assert_prohibits Book, :title, [:not_blank, :alphanumeric] do |book|
|
773
|
+
book.title = ' '
|
774
|
+
end
|
775
|
+
|
776
|
+
assert_prohibits Book, :title, :alphanumeric do |book|
|
777
|
+
book.title = 'asdf@asdf'
|
778
|
+
end
|
779
|
+
|
780
|
+
assert_prohibits Book, :title, :blacklist do |book|
|
781
|
+
book.title = 'foo'
|
782
|
+
end
|
783
|
+
|
784
|
+
ActiveRecord::Migration.deconstrain :books do |t|
|
785
|
+
t.title :not_blank, :alphanumeric, :blacklist
|
786
|
+
end
|
787
|
+
|
788
|
+
assert_allows Book do |book|
|
789
|
+
book.title = ' '
|
790
|
+
end
|
791
|
+
|
792
|
+
assert_allows Book do |book|
|
793
|
+
book.title = 'asdf@asdf'
|
794
|
+
end
|
795
|
+
|
796
|
+
assert_allows Book do |book|
|
797
|
+
book.title = 'foo'
|
798
|
+
end
|
799
|
+
end
|
800
|
+
|
801
|
+
def test_multicolumn_constraint
|
802
|
+
ActiveRecord::Migration.constrain :books, [:title, :isbn], :unique => true
|
803
|
+
|
804
|
+
assert_allows Book do |book|
|
805
|
+
book.title = 'foo'
|
806
|
+
book.isbn = 'bar'
|
807
|
+
end
|
808
|
+
|
809
|
+
assert_allows Book do |book|
|
810
|
+
book.title = 'foo'
|
811
|
+
book.isbn = 'foo'
|
812
|
+
end
|
813
|
+
|
814
|
+
assert_prohibits Book, [:title, :isbn], :unique, 'unique', ActiveRecord::RecordNotUnique do |book|
|
815
|
+
book.title = 'foo'
|
816
|
+
book.isbn = 'bar'
|
817
|
+
end
|
818
|
+
|
819
|
+
ActiveRecord::Migration.deconstrain :books, [:title, :isbn], :unique
|
820
|
+
|
821
|
+
assert_allows Book do |book|
|
822
|
+
book.title = 'foo'
|
823
|
+
book.isbn = 'bar'
|
824
|
+
end
|
825
|
+
end
|
826
|
+
|
827
|
+
def test_multicolumn_constraint_block_syntax
|
828
|
+
ActiveRecord::Migration.constrain :books do |t|
|
829
|
+
t[:title, :isbn].all :unique => true
|
830
|
+
end
|
831
|
+
|
832
|
+
assert_allows Book do |book|
|
833
|
+
book.title = 'foo'
|
834
|
+
book.isbn = 'bar'
|
835
|
+
end
|
836
|
+
|
837
|
+
assert_allows Book do |book|
|
838
|
+
book.title = 'foo'
|
839
|
+
book.isbn = 'foo'
|
840
|
+
end
|
841
|
+
|
842
|
+
assert_prohibits Book, [:title, :isbn], :unique, 'unique', ActiveRecord::RecordNotUnique do |book|
|
843
|
+
book.title = 'foo'
|
844
|
+
book.isbn = 'bar'
|
845
|
+
end
|
846
|
+
|
847
|
+
ActiveRecord::Migration.deconstrain :books do |t|
|
848
|
+
t[:title, :isbn].all :unique
|
849
|
+
end
|
850
|
+
|
851
|
+
assert_allows Book do |book|
|
852
|
+
book.title = 'foo'
|
853
|
+
book.isbn = 'bar'
|
854
|
+
end
|
855
|
+
end
|
856
|
+
|
857
|
+
def test_lowercase
|
858
|
+
ActiveRecord::Migration.constrain :books, :author, :lowercase => true
|
859
|
+
|
860
|
+
assert_prohibits Book, :author, :lowercase do |book|
|
861
|
+
book.author = 'UPPER'
|
862
|
+
end
|
863
|
+
|
864
|
+
assert_allows Book do |book|
|
865
|
+
book.author = 'lower with 1337'
|
866
|
+
end
|
867
|
+
|
868
|
+
ActiveRecord::Migration.deconstrain :books, :author, :lowercase
|
869
|
+
|
870
|
+
assert_allows Book do |book|
|
871
|
+
book.author = 'UPPER'
|
872
|
+
end
|
873
|
+
|
874
|
+
end
|
875
|
+
|
876
|
+
def test_xor
|
877
|
+
ActiveRecord::Migration.constrain :books, [:xor_col_1, :xor_col_2], :xor => true
|
878
|
+
|
879
|
+
assert_prohibits Book, [:xor_col_1, :xor_col_2], :xor do |book|
|
880
|
+
book.xor_col_1 = 123
|
881
|
+
book.xor_col_2 = 321
|
882
|
+
end
|
883
|
+
|
884
|
+
assert_allows Book do |book|
|
885
|
+
book.xor_col_1 = 123
|
886
|
+
end
|
887
|
+
|
888
|
+
assert_allows Book do |book|
|
889
|
+
book.xor_col_2 = 123
|
890
|
+
end
|
891
|
+
|
892
|
+
ActiveRecord::Migration.deconstrain :books, [:xor_col_1, :xor_col_2], :xor
|
893
|
+
|
894
|
+
assert_allows Book do |book|
|
895
|
+
book.xor_col_1 = 123
|
896
|
+
book.xor_col_2 = 123
|
897
|
+
end
|
898
|
+
end
|
899
|
+
end
|