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 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