rein 1.0.0 → 1.1.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.
- checksums.yaml +4 -4
- data/README.md +143 -42
- data/lib/rein/constraint/foreign_key.rb +2 -2
- data/lib/rein/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c374a01203d81386e0d12d076ad23d4b07715f8
|
|
4
|
+
data.tar.gz: 9059371da28496cdd1bd84f37dffddbdbdf4a21f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 83a4fbf3978a81f1f2ecbdda5966a3ae493543ab4a9777cc5086fd4eefbb557571cd27a910d4ecc492e8985319ca9d8f890692bb747570642d706557a390cbf8
|
|
7
|
+
data.tar.gz: 0e4c36f501367e281afac4ac0828232b0b33b7550127c4fdb3fd77ad963c9a406cc010c8b1604678ee3d81d6d6a1ef637de5811e45ebf6ff87656eed90345f29
|
data/README.md
CHANGED
|
@@ -1,75 +1,176 @@
|
|
|
1
1
|
# Rein
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
[Data integrity](http://en.wikipedia.org/wiki/Data_integrity) is a good thing.
|
|
4
|
+
Constraining the values allowed by your application at the database-level,
|
|
5
|
+
rather than at the application-level, is a more robust way of ensuring your
|
|
6
|
+
data stays sane.
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
Unfortunately, ActiveRecord doesn't encourage (or even allow) you to use
|
|
9
|
+
database integrity without resorting to hand-crafted SQL. Rein (pronounced
|
|
10
|
+
"rain") adds a handful of methods to your ActiveRecord migrations so that you
|
|
11
|
+
can easily tame the data in your database.
|
|
7
12
|
|
|
8
|
-
|
|
9
|
-
"good thing". Constraining the allowed values in your database at the
|
|
10
|
-
database-level (rather than solely at the application-level) is a much more
|
|
11
|
-
robust way of ensuring your data stays sane.
|
|
13
|
+
## Table of contents
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
* [Rein](#rein)
|
|
16
|
+
* [Table of contents](#table-of-contents)
|
|
17
|
+
* [Getting started](#getting-started)
|
|
18
|
+
* [Constraint types](#constraint-types)
|
|
19
|
+
* [Foreign key constraints](#foreign-key-constraints)
|
|
20
|
+
* [Inclusion constraints](#inclusion-constraints)
|
|
21
|
+
* [Numericality constraints](#numericality-constraints)
|
|
22
|
+
* [Presence constraints](#presence-constraints)
|
|
23
|
+
* [Example](#example)
|
|
24
|
+
* [License](#license)
|
|
17
25
|
|
|
18
|
-
##
|
|
26
|
+
## Getting started
|
|
19
27
|
|
|
20
28
|
Install the gem:
|
|
21
29
|
|
|
22
30
|
gem install rein
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
## Constraint types
|
|
33
|
+
|
|
34
|
+
### Foreign key constraints
|
|
35
|
+
|
|
36
|
+
A foreign key constraint specifies that the values in a column must match the
|
|
37
|
+
values appearing in some row of another table.
|
|
38
|
+
|
|
39
|
+
For example, let's say that we want to constrain the `author_id` column in the
|
|
40
|
+
`books` table to one of the `id` values in the `authors` table:
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
add_foreign_key_constraint :books, :authors
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Rein will automatically infer the column names for the tables, but if we need
|
|
47
|
+
to be explicit we can using the `referenced` and `referencing` options:
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
add_foreign_key_constraint :books, :authors, referencing: :author_id, referenced: :id
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
We can also specify the behaviour when one of the referenced rows is updated or
|
|
54
|
+
deleted:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
add_foreign_key_constraint :books, :authors, on_delete: :cascade, on_update: :cascade
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Here's all the options for specifying the delete/update behaviour:
|
|
61
|
+
|
|
62
|
+
- `no_action`: if any referencing rows still exist when the constraint is
|
|
63
|
+
checked, an error is raised; this is the default behavior if you do not
|
|
64
|
+
specify anything.
|
|
65
|
+
- `cascade`: when a referenced row is deleted, row(s) referencing it should be
|
|
66
|
+
automatically deleted as well.
|
|
67
|
+
- `set_null`: sets the referencing columns to be nulls when the referenced row
|
|
68
|
+
is deleted.
|
|
69
|
+
- `set_default`: sets the referencing columns to its default values when the
|
|
70
|
+
referenced row is deleted.
|
|
71
|
+
- `restrict`: prevents deletion of a referenced row.
|
|
72
|
+
|
|
73
|
+
### Inclusion constraints
|
|
74
|
+
|
|
75
|
+
*(PostgreSQL only)*
|
|
76
|
+
|
|
77
|
+
An inclusion constraint specifies the possible values that a column value can
|
|
78
|
+
take.
|
|
79
|
+
|
|
80
|
+
For example, we can ensure that `state` column values can only ever be
|
|
81
|
+
`available` or `on_loan`:
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
add_inclusion_constraint :books, :state, in: %w(available on_loan)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Numericality constraints
|
|
88
|
+
|
|
89
|
+
*(PostgreSQL only)*
|
|
90
|
+
|
|
91
|
+
A numericality constraint specifies the range of values that a numeric column
|
|
92
|
+
value can take.
|
|
93
|
+
|
|
94
|
+
For example, we can ensure that the `publication_month` can only ever be a
|
|
95
|
+
value between 1 and 12:
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
add_numericality_constraint :books, :publication_month,
|
|
99
|
+
greater_than_or_equal_to: 1,
|
|
100
|
+
less_than_or_equal_to: 12
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Here's all the options for constraining the values:
|
|
104
|
+
|
|
105
|
+
- `equal_to`
|
|
106
|
+
- `not_equal_to`
|
|
107
|
+
- `less_than`
|
|
108
|
+
- `less_than_or_equal_to`
|
|
109
|
+
- `greater_than`
|
|
110
|
+
- `greater_than_or_equal_to`
|
|
25
111
|
|
|
26
|
-
|
|
112
|
+
### Presence constraints
|
|
27
113
|
|
|
28
|
-
|
|
114
|
+
*(PostgreSQL only)*
|
|
29
115
|
|
|
30
|
-
|
|
116
|
+
A presence constraint ensures that a string column value is non-empty.
|
|
31
117
|
|
|
32
|
-
|
|
118
|
+
A `NOT NULL` constraint will be satisfied by an empty string, but sometimes may
|
|
119
|
+
you want to ensure that there is an actual value for a string:
|
|
33
120
|
|
|
34
|
-
|
|
121
|
+
```ruby
|
|
122
|
+
add_presence_constraint :books, :title
|
|
123
|
+
```
|
|
35
124
|
|
|
36
125
|
## Example
|
|
37
126
|
|
|
38
|
-
Let's look at constraining values for this simple library
|
|
127
|
+
Let's have a look at constraining database values for this simple library
|
|
128
|
+
application.
|
|
39
129
|
|
|
40
130
|
Here we have a table of authors:
|
|
41
131
|
|
|
42
|
-
|
|
43
|
-
|
|
132
|
+
```ruby
|
|
133
|
+
create_table :authors do |t|
|
|
134
|
+
t.string :name, null: false
|
|
135
|
+
t.timestamps, null: false
|
|
136
|
+
end
|
|
44
137
|
|
|
45
|
-
|
|
46
|
-
|
|
138
|
+
# An author must have a name.
|
|
139
|
+
add_presence_constraint :authors, :name
|
|
140
|
+
```
|
|
47
141
|
|
|
48
|
-
|
|
142
|
+
We also have a table of books:
|
|
49
143
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
144
|
+
```ruby
|
|
145
|
+
create_table :books do |t|
|
|
146
|
+
t.belongs_to :author, null: false
|
|
147
|
+
t.string :title, null: false
|
|
148
|
+
t.string :state, null: false
|
|
149
|
+
t.integer :published_year, null: false
|
|
150
|
+
t.integer :published_month, null: false
|
|
151
|
+
t.timestamps, null: false
|
|
152
|
+
end
|
|
56
153
|
|
|
57
|
-
|
|
58
|
-
|
|
154
|
+
# A book should always belong to an author. The database should prevent us from
|
|
155
|
+
# deleteing an author who has books.
|
|
156
|
+
add_foreign_key_constraint :books, :authors, on_delete: :restrict
|
|
59
157
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
add_foreign_key_constraint :books, :authors, :on_delete => :restrict
|
|
158
|
+
# A book must have a non-empty title.
|
|
159
|
+
add_presence_constraint :books, :title
|
|
63
160
|
|
|
64
|
-
|
|
65
|
-
|
|
161
|
+
# State is always either "available" or "on_loan".
|
|
162
|
+
add_inclusion_constraint :books, :state, in: %w(available on_loan)
|
|
66
163
|
|
|
67
|
-
|
|
68
|
-
|
|
164
|
+
# Our library doesn't deal in classics.
|
|
165
|
+
add_numericality_constraint :books, :published_year,
|
|
166
|
+
greater_than_or_equal_to: 1980
|
|
69
167
|
|
|
70
|
-
|
|
71
|
-
|
|
168
|
+
# Month is always between 1 and 12.
|
|
169
|
+
add_numericality_constraint :books, :published_month,
|
|
170
|
+
greater_than_or_equal_to: 1,
|
|
171
|
+
less_than_or_equal_to: 12
|
|
172
|
+
```
|
|
72
173
|
|
|
73
174
|
## License
|
|
74
175
|
|
|
75
|
-
|
|
176
|
+
Rein is licensed under the [MIT License](/LICENSE).
|
|
@@ -45,8 +45,8 @@ module Rein
|
|
|
45
45
|
when :no_action then "NO ACTION"
|
|
46
46
|
when :cascade then "CASCADE"
|
|
47
47
|
when :restrict then "RESTRICT"
|
|
48
|
-
when :nullify then "SET NULL"
|
|
49
|
-
when :default then "SET DEFAULT"
|
|
48
|
+
when :set_null, :nullify then "SET NULL"
|
|
49
|
+
when :set_default, :default then "SET DEFAULT"
|
|
50
50
|
else
|
|
51
51
|
raise "Unknown referential action '#{action}'"
|
|
52
52
|
end
|
data/lib/rein/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rein
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joshua Bassett
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-03-
|
|
11
|
+
date: 2017-03-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -125,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
125
125
|
version: '0'
|
|
126
126
|
requirements: []
|
|
127
127
|
rubyforge_project:
|
|
128
|
-
rubygems_version: 2.
|
|
128
|
+
rubygems_version: 2.6.11
|
|
129
129
|
signing_key:
|
|
130
130
|
specification_version: 4
|
|
131
131
|
summary: Database constraints made easy for ActiveRecord.
|