rein 1.1.0 → 2.0.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/CHANGELOG.md +8 -0
- data/README.md +80 -0
- data/Rakefile +1 -1
- data/lib/rein.rb +2 -0
- data/lib/rein/constraint/inclusion.rb +7 -2
- data/lib/rein/constraint/numericality.rb +9 -0
- data/lib/rein/constraint/presence.rb +11 -3
- data/lib/rein/type/enum.rb +23 -0
- data/lib/rein/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0615a7f2e565c2f358a695bde5ca27c1dc38dd09
|
4
|
+
data.tar.gz: 4dc8082ed6921296954d8802b296f74ca9ad2fd6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 662ac24aca4142d7dc22db7a5de022dd89df180c745a8d944551dabdc29ae62b0c2fd9a92a353bbd9a4c4e28debf7c500879f98e84d046d5377bb8bb285f8c63
|
7
|
+
data.tar.gz: faf7c737bce89979103b5f382742982e108512e0598d041fae995c8b5c5c10fbfa73168b53b26a434b6134298921539a95861fe886b81eac202ffabe834ae727
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -20,6 +20,9 @@ can easily tame the data in your database.
|
|
20
20
|
* [Inclusion constraints](#inclusion-constraints)
|
21
21
|
* [Numericality constraints](#numericality-constraints)
|
22
22
|
* [Presence constraints](#presence-constraints)
|
23
|
+
* [Data types](#data-types)
|
24
|
+
* [Enumerated types](#enumerated-types)
|
25
|
+
* [Views](#views)
|
23
26
|
* [Example](#example)
|
24
27
|
* [License](#license)
|
25
28
|
|
@@ -70,6 +73,12 @@ Here's all the options for specifying the delete/update behaviour:
|
|
70
73
|
referenced row is deleted.
|
71
74
|
- `restrict`: prevents deletion of a referenced row.
|
72
75
|
|
76
|
+
To remove a foreign key constraint:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
remove_foreign_key_constraint :books, :authors
|
80
|
+
```
|
81
|
+
|
73
82
|
### Inclusion constraints
|
74
83
|
|
75
84
|
*(PostgreSQL only)*
|
@@ -84,6 +93,12 @@ For example, we can ensure that `state` column values can only ever be
|
|
84
93
|
add_inclusion_constraint :books, :state, in: %w(available on_loan)
|
85
94
|
```
|
86
95
|
|
96
|
+
To remove an inclusion constraint:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
remove_inclusion_constraint :books, :state
|
100
|
+
```
|
101
|
+
|
87
102
|
### Numericality constraints
|
88
103
|
|
89
104
|
*(PostgreSQL only)*
|
@@ -109,6 +124,22 @@ Here's all the options for constraining the values:
|
|
109
124
|
- `greater_than`
|
110
125
|
- `greater_than_or_equal_to`
|
111
126
|
|
127
|
+
You may also include an `if` option to enforce the constraint only under certain conditions,
|
128
|
+
like so:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
add_numericality_constraint :books, :publication_month,
|
132
|
+
greater_than_or_equal_to: 1,
|
133
|
+
less_than_or_equal_to: 12,
|
134
|
+
if: "status = 'published'"
|
135
|
+
```
|
136
|
+
|
137
|
+
To remove a numericality constraint:
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
remove_numericality_constraint :books, :publication_month
|
141
|
+
```
|
142
|
+
|
112
143
|
### Presence constraints
|
113
144
|
|
114
145
|
*(PostgreSQL only)*
|
@@ -122,6 +153,55 @@ you want to ensure that there is an actual value for a string:
|
|
122
153
|
add_presence_constraint :books, :title
|
123
154
|
```
|
124
155
|
|
156
|
+
If you only want to enforce the constraint under certain conditions,
|
157
|
+
you can pass an optional `if` option:
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
add_presence_constraint :books, :isbn, if: "status = 'published'"
|
161
|
+
```
|
162
|
+
|
163
|
+
To remove a presence constraint:
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
remove_presence_constraint :books, :title
|
167
|
+
```
|
168
|
+
|
169
|
+
## Data types
|
170
|
+
|
171
|
+
### Enumerated types
|
172
|
+
|
173
|
+
*(PostgreSQL only)*
|
174
|
+
|
175
|
+
An enum is a data type that represents a static, ordered set of values.
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
create_enum_type :book_type, ['paperback', 'hardcover']
|
179
|
+
```
|
180
|
+
|
181
|
+
To drop an enum type from the database:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
drop_enum_type :book_type
|
185
|
+
```
|
186
|
+
|
187
|
+
## Views
|
188
|
+
|
189
|
+
A view is a named query that you can refer to just like an ordinary table. You
|
190
|
+
can even create ActiveRecord models that are backed by views in your database.
|
191
|
+
|
192
|
+
For example, we can define an `available_books` view that returns only the
|
193
|
+
books which are currently available:
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
create_view(:available_books, "SELECT * FROM books WHERE state = 'available'")
|
197
|
+
```
|
198
|
+
|
199
|
+
To drop a view from the database:
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
drop_view(:available_books)
|
203
|
+
```
|
204
|
+
|
125
205
|
## Example
|
126
206
|
|
127
207
|
Let's have a look at constraining database values for this simple library
|
data/Rakefile
CHANGED
data/lib/rein.rb
CHANGED
@@ -6,6 +6,7 @@ require "rein/constraint/foreign_key"
|
|
6
6
|
require "rein/constraint/inclusion"
|
7
7
|
require "rein/constraint/numericality"
|
8
8
|
require "rein/constraint/presence"
|
9
|
+
require "rein/type/enum"
|
9
10
|
require "rein/view"
|
10
11
|
|
11
12
|
module ActiveRecord
|
@@ -28,6 +29,7 @@ module ActiveRecord
|
|
28
29
|
include Rein::Constraint::Inclusion
|
29
30
|
include Rein::Constraint::Numericality
|
30
31
|
include Rein::Constraint::Presence
|
32
|
+
include Rein::Type::Enum
|
31
33
|
include Rein::View
|
32
34
|
end
|
33
35
|
end
|
@@ -7,11 +7,16 @@ module Rein
|
|
7
7
|
include ActiveRecord::ConnectionAdapters::Quoting
|
8
8
|
|
9
9
|
def add_inclusion_constraint(table, attribute, options = {})
|
10
|
-
name
|
11
|
-
values
|
10
|
+
name = "#{table}_#{attribute}"
|
11
|
+
values = options[:in].map { |value| quote(value) }.join(", ")
|
12
12
|
conditions = "#{attribute} IN (#{values})"
|
13
13
|
execute("ALTER TABLE #{table} ADD CONSTRAINT #{name} CHECK (#{conditions})")
|
14
14
|
end
|
15
|
+
|
16
|
+
def remove_inclusion_constraint(table, attribute)
|
17
|
+
name = "#{table}_#{attribute}"
|
18
|
+
execute("ALTER TABLE #{table} DROP CONSTRAINT #{name}")
|
19
|
+
end
|
15
20
|
end
|
16
21
|
end
|
17
22
|
end
|
@@ -19,8 +19,17 @@ module Rein
|
|
19
19
|
[attribute, operator, value].join(" ")
|
20
20
|
end.join(" AND ")
|
21
21
|
|
22
|
+
if options[:if].present?
|
23
|
+
conditions = "NOT (#{options[:if]}) OR (#{conditions})"
|
24
|
+
end
|
25
|
+
|
22
26
|
execute("ALTER TABLE #{table} ADD CONSTRAINT #{name} CHECK (#{conditions})")
|
23
27
|
end
|
28
|
+
|
29
|
+
def remove_numericality_constraint(table, attribute)
|
30
|
+
name = "#{table}_#{attribute}"
|
31
|
+
execute("ALTER TABLE #{table} DROP CONSTRAINT #{name}")
|
32
|
+
end
|
24
33
|
end
|
25
34
|
end
|
26
35
|
end
|
@@ -4,11 +4,19 @@ module Rein
|
|
4
4
|
module Presence
|
5
5
|
include ActiveRecord::ConnectionAdapters::Quoting
|
6
6
|
|
7
|
-
def add_presence_constraint(table, attribute)
|
8
|
-
name
|
9
|
-
conditions = "#{attribute} !~ '
|
7
|
+
def add_presence_constraint(table, attribute, options = {})
|
8
|
+
name = "#{table}_#{attribute}"
|
9
|
+
conditions = "#{attribute} !~ '^\\s*$'"
|
10
|
+
if options[:if].present?
|
11
|
+
conditions = "NOT (#{options[:if]}) OR (#{conditions})"
|
12
|
+
end
|
10
13
|
execute("ALTER TABLE #{table} ADD CONSTRAINT #{name} CHECK (#{conditions})")
|
11
14
|
end
|
15
|
+
|
16
|
+
def remove_presence_constraint(table, attribute)
|
17
|
+
name = "#{table}_#{attribute}"
|
18
|
+
execute("ALTER TABLE #{table} DROP CONSTRAINT #{name}")
|
19
|
+
end
|
12
20
|
end
|
13
21
|
end
|
14
22
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "active_record/connection_adapters/abstract/quoting"
|
2
|
+
|
3
|
+
module Rein
|
4
|
+
module Type
|
5
|
+
# This module contains methods for defining enum types.
|
6
|
+
module Enum
|
7
|
+
include ActiveRecord::ConnectionAdapters::Quoting
|
8
|
+
|
9
|
+
def create_enum_type(enum_name, enum_values = [])
|
10
|
+
enum_values = enum_values.map { |value| quote(value) }.join(", ")
|
11
|
+
execute("CREATE TYPE #{enum_name} AS ENUM (#{enum_values})")
|
12
|
+
end
|
13
|
+
|
14
|
+
def drop_enum_type(enum_name)
|
15
|
+
execute("DROP TYPE #{enum_name}")
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_enum_value(enum_name, new_value)
|
19
|
+
execute("ALTER TYPE #{enum_name} ADD VALUE #{quote(new_value)}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
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:
|
4
|
+
version: 2.0.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-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -92,6 +92,7 @@ files:
|
|
92
92
|
- ".rubocop.yml"
|
93
93
|
- ".travis.yml"
|
94
94
|
- ".yardopts"
|
95
|
+
- CHANGELOG.md
|
95
96
|
- Gemfile
|
96
97
|
- LICENSE
|
97
98
|
- README.md
|
@@ -102,6 +103,7 @@ files:
|
|
102
103
|
- lib/rein/constraint/numericality.rb
|
103
104
|
- lib/rein/constraint/presence.rb
|
104
105
|
- lib/rein/constraint/primary_key.rb
|
106
|
+
- lib/rein/type/enum.rb
|
105
107
|
- lib/rein/version.rb
|
106
108
|
- lib/rein/view.rb
|
107
109
|
- rein.gemspec
|