rein 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5c374a01203d81386e0d12d076ad23d4b07715f8
4
- data.tar.gz: 9059371da28496cdd1bd84f37dffddbdbdf4a21f
3
+ metadata.gz: 0615a7f2e565c2f358a695bde5ca27c1dc38dd09
4
+ data.tar.gz: 4dc8082ed6921296954d8802b296f74ca9ad2fd6
5
5
  SHA512:
6
- metadata.gz: 83a4fbf3978a81f1f2ecbdda5966a3ae493543ab4a9777cc5086fd4eefbb557571cd27a910d4ecc492e8985319ca9d8f890692bb747570642d706557a390cbf8
7
- data.tar.gz: 0e4c36f501367e281afac4ac0828232b0b33b7550127c4fdb3fd77ad963c9a406cc010c8b1604678ee3d81d6d6a1ef637de5811e45ebf6ff87656eed90345f29
6
+ metadata.gz: 662ac24aca4142d7dc22db7a5de022dd89df180c745a8d944551dabdc29ae62b0c2fd9a92a353bbd9a4c4e28debf7c500879f98e84d046d5377bb8bb285f8c63
7
+ data.tar.gz: faf7c737bce89979103b5f382742982e108512e0598d041fae995c8b5c5c10fbfa73168b53b26a434b6134298921539a95861fe886b81eac202ffabe834ae727
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ ## 2.0.0
4
+
5
+ - Add support for enumerated types.
6
+ - Add `if` option to numericality constraints.
7
+ - Add `if` option to presence constraints.
8
+ - Fix a bug in presence contraints.
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
@@ -5,4 +5,4 @@ require "rubocop/rake_task"
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
  RuboCop::RakeTask.new
7
7
 
8
- task default: [:spec, :rubocop]
8
+ task default: %w(spec rubocop)
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 = "#{table}_#{attribute}"
11
- values = options[:in].map { |value| quote(value) }.join(", ")
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 = "#{table}_#{attribute}"
9
- conditions = "#{attribute} !~ '^\s*$'"
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
@@ -1,3 +1,3 @@
1
1
  module Rein
2
- VERSION = "1.1.0".freeze
2
+ VERSION = "2.0.0".freeze
3
3
  end
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.1.0
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-22 00:00:00.000000000 Z
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