database_validations 0.5.1 → 0.6.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
  SHA256:
3
- metadata.gz: 4817334b7a4a7ae57f43e69be04b5969dbb35dcbb39f4bd2ebc52603cf149a15
4
- data.tar.gz: b899b604b2f72021269c39372c60acf0fb4a6805e4d3e2b5f606320aa165bb9a
3
+ metadata.gz: 34f55425dd0da6279bd235d760df174ac1f028365f00d88be653b601207b526d
4
+ data.tar.gz: 8ef9de8f18ba558c5c1cfb9be9af9f0257cd188df35b05545fc479490f799316
5
5
  SHA512:
6
- metadata.gz: d2b50fd0375c72c71ce1a443131a3c16f84118153947a373280ee9b28f6d6572abf3576acbf4be0660e3d436f30abce62d0072c2297c47e557dc894c002ceb74
7
- data.tar.gz: 53e6a6363cc2d64763e9ba3c6089911dc09950c799ffcdbfd51f7d792e48c04f82cb8fc47435b01fad64567ba7ba625c865788ccaf73e79a3745e734f752fed9
6
+ metadata.gz: 8ad092489894f94f52ac4ed99b83dedb383bd0643af8f938c8225c3d1f1cf69d625d2b687346492f45980851a93b45489c76043f5c98be836fcc3739d4f4e1aa
7
+ data.tar.gz: ee668b15d32473eda6b01fc18ab4c9d7336dfd415ee42e33e2e27168f444a3bef7fc4067b6c59793ef5c065cccd5ddca28469439d3c53bb213bc4468e6c42bdb
data/README.md CHANGED
@@ -125,6 +125,8 @@ The list of options to add support:
125
125
  - `allow_nil`: If set to `true`, skips this validation if the attribute is `nil` (default is `false`).
126
126
  - `allow_blank`: If set to `true`, skips this validation if the attribute is blank (default is `false`).
127
127
 
128
+ **Note**: For `PosgreSQL`, it is possible to replace these options with combination of other supported options.
129
+
128
130
  ### Benchmark ([code](https://github.com/toptal/database_validations/blob/master/benchmarks/uniqueness_validator_benchmark.rb))
129
131
 
130
132
  | Case | Validator | SQLite | PostgreSQL | MySQL |
@@ -136,6 +138,26 @@ The list of options to add support:
136
138
  | Each hundredth item is duplicate | validates_db_uniqueness_of | 3.534k (± 5.6%) i/s - 17.748k in 5.039277s | 1.351k (± 6.5%) i/s - 6.750k in 5.017280s | 1.436k (±11.6%) i/s - 7.154k in 5.062644s |
137
139
  | | validates_uniqueness_of | 2.121k (± 6.8%) i/s - 10.653k in 5.049739s | 658.199 (± 6.1%) i/s - 3.350k in 5.110176s | 596.024 (± 6.7%) i/s - 2.989k in 5.041497s |
138
140
 
141
+ ## Testing (RSpec)
142
+
143
+ Add `require database_validations/rspec/matchers'` to your `spec` file.
144
+
145
+ ### validate_db_uniqueness_of
146
+
147
+ Example:
148
+
149
+ ```ruby
150
+ class User < ActiveRecord::Base
151
+ validates_db_uniqueness_of :field, message: 'duplicate', where: '(some_field IS NULL)', scope: :another_field
152
+ end
153
+
154
+ describe 'validations' do
155
+ subject { User }
156
+
157
+ it { is_expected.to validate_db_uniqueness_of(:field).with_message('duplicate').with_where('(some_field IS NULL)').scoped_to(:another_field) }
158
+ end
159
+ ```
160
+
139
161
  ## Development
140
162
 
141
163
  You need to have installed and running `postgresql` and `mysql`.
@@ -1,13 +1,15 @@
1
1
  require 'active_record'
2
2
 
3
3
  require 'database_validations/version'
4
- require 'database_validations/railtie' if defined?(Rails)
5
- require 'database_validations/uniqueness_validator'
6
- require 'database_validations/uniqueness_options'
7
- require 'database_validations/uniqueness_options_storage'
8
- require 'database_validations/errors'
9
- require 'database_validations/helpers'
10
- require 'database_validations/adapters'
4
+
5
+ require 'database_validations/rails/railtie' if defined?(Rails)
6
+
7
+ require 'database_validations/validations/uniqueness_validator'
8
+ require 'database_validations/validations/uniqueness_options'
9
+ require 'database_validations/validations/uniqueness_options_storage'
10
+ require 'database_validations/validations/errors'
11
+ require 'database_validations/validations/helpers'
12
+ require 'database_validations/validations/adapters'
11
13
 
12
14
  module DatabaseValidations
13
15
  extend ActiveSupport::Concern
@@ -3,7 +3,7 @@ require 'active_record/railtie'
3
3
  module DatabaseValidations
4
4
  class Railtie < Rails::Railtie
5
5
  rake_tasks do
6
- load 'tasks/database_validations.rake'
6
+ load 'database_validations/tasks/database_validations.rake'
7
7
 
8
8
  Rake.application.in_namespace(:db) do |namespace|
9
9
  namespace.tasks.each do |task|
@@ -0,0 +1 @@
1
+ require 'database_validations/rspec/uniqueness_validator_matcher'
@@ -0,0 +1,58 @@
1
+ # @scope Models
2
+ #
3
+ # Matches when model validate database uniqueness of some field.
4
+ #
5
+ # Modifiers:
6
+ # * `with_message(message)` -- specifies a message of the error;
7
+ # * `scoped_to(scope)` -- specifies a scope for the validator;
8
+ # * `with_where(where)` -- specifies a where condition for the validator;
9
+ #
10
+ # Example:
11
+ #
12
+ # ```ruby
13
+ # it { expect(Model).to validate_db_uniqueness_of(:field) }
14
+ # ```
15
+ RSpec::Matchers.define :validate_db_uniqueness_of do |field|
16
+ chain(:with_message) do |message|
17
+ @message = message
18
+ end
19
+
20
+ chain(:scoped_to) do |*scope|
21
+ @scope = scope.flatten
22
+ end
23
+
24
+ chain(:with_where) do |where|
25
+ @where = where
26
+ end
27
+
28
+ match do |model|
29
+ @validators = []
30
+
31
+ DatabaseValidations::Helpers.each_validator(model) do |validator|
32
+ @validators << {
33
+ field: validator.field,
34
+ scope: validator.scope,
35
+ where: validator.where_clause,
36
+ message: validator.message
37
+ }
38
+ end
39
+
40
+ @validators.include?(field: field, scope: Array.wrap(@scope), where: @where, message: @message)
41
+ end
42
+
43
+ description do
44
+ desc = "validate database uniqueness of #{field}. "
45
+ desc += "With options - " if @message || @scope || @where
46
+ desc += "message: '#{@message}'; " if @message
47
+ desc += "scope: #{@scope}; " if @scope
48
+ desc += "where: '#{@where}'. " if @where
49
+ desc
50
+ end
51
+
52
+ failure_message do
53
+ <<-TEXT
54
+ There is no such database uniqueness validator.
55
+ Available validators are: #{@validators}.
56
+ TEXT
57
+ end
58
+ end
@@ -0,0 +1,9 @@
1
+ module DatabaseValidations
2
+ module Tasks
3
+ namespace :database_validations do
4
+ task :skip_db_uniqueness_validator_index_check do
5
+ ENV['SKIP_DB_UNIQUENESS_VALIDATOR_INDEX_CHECK'] = 'true'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,7 +1,7 @@
1
- require 'database_validations/adapters/base_adapter'
2
- require 'database_validations/adapters/sqlite_adapter'
3
- require 'database_validations/adapters/postgresql_adapter'
4
- require 'database_validations/adapters/mysql_adapter'
1
+ require 'database_validations/validations/adapters/base_adapter'
2
+ require 'database_validations/validations/adapters/sqlite_adapter'
3
+ require 'database_validations/validations/adapters/postgresql_adapter'
4
+ require 'database_validations/validations/adapters/mysql_adapter'
5
5
 
6
6
  module DatabaseValidations
7
7
  module Adapters
@@ -27,7 +27,7 @@ module DatabaseValidations
27
27
  end
28
28
 
29
29
  def unify_columns(*columns)
30
- columns.flatten.map(&:to_s).sort
30
+ columns.flatten.compact.map(&:to_s).sort
31
31
  end
32
32
 
33
33
  def generate_key(*columns)
@@ -1,5 +1,7 @@
1
1
  module DatabaseValidations
2
2
  class UniquenessOptions
3
+ attr_reader :field
4
+
3
5
  def initialize(field, options, adapter)
4
6
  @field = field
5
7
  @options = options
@@ -34,16 +36,24 @@ module DatabaseValidations
34
36
  end
35
37
 
36
38
  def columns
37
- @columns ||= Helpers.unify_columns(field, Array.wrap(options[:scope]))
39
+ @columns ||= Helpers.unify_columns(field, scope)
38
40
  end
39
41
 
40
42
  def where_clause
41
43
  @where_clause ||= options[:where]
42
44
  end
43
45
 
46
+ def message
47
+ @message ||= options[:message]
48
+ end
49
+
50
+ def scope
51
+ @scope ||= Array.wrap(options[:scope])
52
+ end
53
+
44
54
  private
45
55
 
46
- attr_reader :adapter, :field, :options
56
+ attr_reader :adapter, :options
47
57
 
48
58
  def condition_passes?(condition, instance)
49
59
  if condition.is_a?(Symbol)
@@ -1,3 +1,3 @@
1
1
  module DatabaseValidations
2
- VERSION = "0.5.1"
2
+ VERSION = '0.6.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: database_validations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgeniy Demin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-25 00:00:00.000000000 Z
11
+ date: 2018-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -128,6 +128,20 @@ dependencies:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
130
  version: '3.0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: climate_control
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '0.2'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '0.2'
131
145
  description: |-
132
146
  ActiveRecord provides validations on app level but it won't guarantee the
133
147
  consistent. In some cases, like `validates_uniqueness_of` it executes
@@ -144,19 +158,21 @@ files:
144
158
  - LICENSE.txt
145
159
  - README.md
146
160
  - lib/database_validations.rb
147
- - lib/database_validations/adapters.rb
148
- - lib/database_validations/adapters/base_adapter.rb
149
- - lib/database_validations/adapters/mysql_adapter.rb
150
- - lib/database_validations/adapters/postgresql_adapter.rb
151
- - lib/database_validations/adapters/sqlite_adapter.rb
152
- - lib/database_validations/errors.rb
153
- - lib/database_validations/helpers.rb
154
- - lib/database_validations/railtie.rb
155
- - lib/database_validations/uniqueness_options.rb
156
- - lib/database_validations/uniqueness_options_storage.rb
157
- - lib/database_validations/uniqueness_validator.rb
161
+ - lib/database_validations/rails/railtie.rb
162
+ - lib/database_validations/rspec/matchers.rb
163
+ - lib/database_validations/rspec/uniqueness_validator_matcher.rb
164
+ - lib/database_validations/tasks/database_validations.rake
165
+ - lib/database_validations/validations/adapters.rb
166
+ - lib/database_validations/validations/adapters/base_adapter.rb
167
+ - lib/database_validations/validations/adapters/mysql_adapter.rb
168
+ - lib/database_validations/validations/adapters/postgresql_adapter.rb
169
+ - lib/database_validations/validations/adapters/sqlite_adapter.rb
170
+ - lib/database_validations/validations/errors.rb
171
+ - lib/database_validations/validations/helpers.rb
172
+ - lib/database_validations/validations/uniqueness_options.rb
173
+ - lib/database_validations/validations/uniqueness_options_storage.rb
174
+ - lib/database_validations/validations/uniqueness_validator.rb
158
175
  - lib/database_validations/version.rb
159
- - lib/tasks/database_validations.rake
160
176
  homepage: https://github.com/toptal/database_validations
161
177
  licenses:
162
178
  - MIT
@@ -1,5 +0,0 @@
1
- namespace :database_validations do
2
- task :skip_db_uniqueness_validator_index_check do
3
- ENV['SKIP_DB_UNIQUENESS_VALIDATOR_INDEX_CHECK'] = 'true'
4
- end
5
- end