database_validations 0.4.0 → 0.5.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: 0a94ceacef368255d4e55eaf4ac852a839b78238ca47a0d3bceac249e4a1ded3
4
- data.tar.gz: a38b1061a9c345543aa353c5048b2472026c4cb806991c64c5e2b23e48ac6fd7
3
+ metadata.gz: 0540cd1970a66666d9d87489076205155314a0b6e67c105c053fa61f8f22b19a
4
+ data.tar.gz: c8e0a0cac2b2e86571159053e29b840bba391527060adcd501f3f7a4836e0c5e
5
5
  SHA512:
6
- metadata.gz: 3f1543f0a6b04ce50064e74bc56fa059153f7660774932008c5ef50699bb02c31b88f9cee8fa01ef519128932caefe770364536867a5c108ec42fee3e6a31984
7
- data.tar.gz: b0d74dc13be3a54b9bc95c20f5ce24673e5a586392f3d63d3e5f4ad171fadf49bf3b202e4e3e12480af5bf3eba4ed935c9a4cb75a2638248e09c1ae835a634a2
6
+ metadata.gz: b79ba0d354e4337a39d8182de5dca5080980fa97a2b2d4094cba86347f583b7afa2a61b3c1e7440eaacb0f09344b9dd7dbbea553abf8cb64b361a35c79c7c74b
7
+ data.tar.gz: 7a899554d2373b049fc360939ae493dee275648f52d32f243c2c22338e9d643850b6a60749ef524e5bfd8658f47a98209cd87ec3df94f2454650361709221a03
data/README.md CHANGED
@@ -81,8 +81,27 @@ List of supported options from `validates_uniqueness_of` validator:
81
81
 
82
82
  - `scope`: One or more columns by which to limit the scope of the uniqueness constraint.
83
83
  - `message`: Specifies a custom error message (default is: "has already been taken").
84
+ - `if`: Specifies a method or proc to call to determine if the validation should occur
85
+ (e.g. <tt>if: :allow_validation</tt>, or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method or
86
+ proc should return or evaluate to a `true` or `false` value.
87
+ - `unless`: Specifies a method or proc to call to determine if the validation should not
88
+ occur (e.g. <tt>unless: :skip_validation</tt>, or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>).
89
+ The method or proc should return or evaluate to a `true` or `false` value.
84
90
 
85
- **Keep in mind**: Even when we don't support `case_sensitive`, `allow_nil` and `allow_blank` options now, the following:
91
+ **Keep in mind**: Both `if` and `unless` options are used only for `valid?` method and provided only for performance reason.
92
+
93
+ ```ruby
94
+ class User < ActiveRecord::Base
95
+ validates_db_uniqueness_of :email, if: -> { email && email_changed? }
96
+ end
97
+
98
+ user = User.create(email: 'email@mail.com', field: 'field')
99
+ user.field = 'another'
100
+
101
+ user.valid? # Will not query the database
102
+ ```
103
+
104
+ **Backward compatibility**: Even when we don't support `case_sensitive`, `allow_nil` and `allow_blank` options now, the following:
86
105
 
87
106
  ```ruby
88
107
  validates_db_uniqueness_of :email
@@ -106,12 +125,6 @@ The list of options to add support:
106
125
  - `case_sensitive`: Looks for an exact match. Ignored by non-text columns (`true` by default).
107
126
  - `allow_nil`: If set to `true`, skips this validation if the attribute is `nil` (default is `false`).
108
127
  - `allow_blank`: If set to `true`, skips this validation if the attribute is blank (default is `false`).
109
- - `if`: Specifies a method, proc or string to call to determine if the validation should occur
110
- (e.g. <tt>if: :allow_validation</tt>, or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
111
- proc or string should return or evaluate to a `true` or `false` value.
112
- - `unless`: Specifies a method, proc or string to call to determine if the validation should not
113
- occur (e.g. <tt>unless: :skip_validation</tt>, or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>).
114
- The method, proc or string should return or evaluate to a `true` or `false` value.
115
128
 
116
129
  ### Benchmark ([code](https://github.com/toptal/database_validations/blob/master/benchmarks/uniqueness_validator_benchmark.rb))
117
130
 
@@ -1,7 +1,7 @@
1
1
  module DatabaseValidations
2
2
  module Adapters
3
3
  class MysqlAdapter < BaseAdapter
4
- SUPPORTED_OPTIONS = %i[scope message].freeze
4
+ SUPPORTED_OPTIONS = %i[scope message if unless].freeze
5
5
  ADAPTER = :mysql2
6
6
 
7
7
  def error_columns(error_message)
@@ -1,7 +1,7 @@
1
1
  module DatabaseValidations
2
2
  module Adapters
3
3
  class PostgresqlAdapter < BaseAdapter
4
- SUPPORTED_OPTIONS = %i[scope message where].freeze
4
+ SUPPORTED_OPTIONS = %i[scope message where if unless].freeze
5
5
  ADAPTER = :postgresql
6
6
 
7
7
  def error_columns(error_message)
@@ -1,7 +1,7 @@
1
1
  module DatabaseValidations
2
2
  module Adapters
3
3
  class SqliteAdapter < BaseAdapter
4
- SUPPORTED_OPTIONS = %i[scope message].freeze
4
+ SUPPORTED_OPTIONS = %i[scope message if unless].freeze
5
5
  ADAPTER = :sqlite
6
6
 
7
7
  def error_columns(error_message)
@@ -24,6 +24,11 @@ module DatabaseValidations
24
24
  .tap { |opts| opts[:conditions] = -> { where(where_clause_str) } if where_clause }
25
25
  end
26
26
 
27
+ def if_and_unless_pass?(instance)
28
+ (options[:if].nil? || condition_passes?(options[:if], instance)) &&
29
+ (options[:unless].nil? || !condition_passes?(options[:unless], instance))
30
+ end
31
+
27
32
  def key
28
33
  @key ||= Helpers.generate_key(columns)
29
34
  end
@@ -36,6 +41,20 @@ module DatabaseValidations
36
41
  @where_clause ||= options[:where]
37
42
  end
38
43
 
44
+ private
45
+
46
+ attr_reader :adapter, :field, :options
47
+
48
+ def condition_passes?(condition, instance)
49
+ if condition.is_a?(Symbol)
50
+ instance.__send__(condition)
51
+ elsif condition.is_a?(Proc) && condition.arity == 0
52
+ instance.instance_exec(&condition)
53
+ else
54
+ instance.instance_eval(&condition)
55
+ end
56
+ end
57
+
39
58
  def raise_if_unsupported_options!
40
59
  options.except(:attributes).each_key do |option|
41
60
  unless adapter.support_option?(option)
@@ -47,10 +66,6 @@ module DatabaseValidations
47
66
  def raise_if_index_missed!
48
67
  raise Errors::IndexNotFound.new(columns, where_clause, adapter.indexes) unless adapter.find_index(columns, where_clause)
49
68
  end
50
-
51
- private
52
-
53
- attr_reader :adapter, :field, :options
54
69
  end
55
70
  end
56
71
 
@@ -9,7 +9,9 @@ module DatabaseValidations
9
9
  output = super(context)
10
10
 
11
11
  Helpers.each_validator(self.class) do |validator|
12
- validates_with(ActiveRecord::Validations::UniquenessValidator, validator.validates_uniqueness_options)
12
+ if validator.if_and_unless_pass?(self)
13
+ validates_with(ActiveRecord::Validations::UniquenessValidator, validator.validates_uniqueness_options)
14
+ end
13
15
  end
14
16
 
15
17
  errors.empty? && output
@@ -1,3 +1,3 @@
1
1
  module DatabaseValidations
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.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.4.0
4
+ version: 0.5.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-22 00:00:00.000000000 Z
11
+ date: 2018-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord