database_validations 0.3.7 → 0.4.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
  SHA256:
3
- metadata.gz: aefb40cecf33b68606f21a491cd41ffa3e1bc4ffcf891b837b9b8693e04f2239
4
- data.tar.gz: ec3c2ab6955ec4f5da93804bcb6f2382d577331553b9d710af75a62cf9e8ccea
3
+ metadata.gz: 0a94ceacef368255d4e55eaf4ac852a839b78238ca47a0d3bceac249e4a1ded3
4
+ data.tar.gz: a38b1061a9c345543aa353c5048b2472026c4cb806991c64c5e2b23e48ac6fd7
5
5
  SHA512:
6
- metadata.gz: 1c341fa892d214a3fce105e683c90b5633c7c8ccc5917c675762e710cde2443e332bf66768831b772436c6eb6bfd823136411f409e0c16ef58cb85347f8b87c8
7
- data.tar.gz: c6a838adc69c1558acede0e38df24d30bac20d7c348951c8059966daf59e649ae7887879810e68f88df88d69b277451a7fe476bca8a237842c970103184c073b
6
+ metadata.gz: 3f1543f0a6b04ce50064e74bc56fa059153f7660774932008c5ef50699bb02c31b88f9cee8fa01ef519128932caefe770364536867a5c108ec42fee3e6a31984
7
+ data.tar.gz: b0d74dc13be3a54b9bc95c20f5ce24673e5a586392f3d63d3e5f4ad171fadf49bf3b202e4e3e12480af5bf3eba4ed935c9a4cb75a2638248e09c1ae835a634a2
data/README.md CHANGED
@@ -77,7 +77,7 @@ User.create!(email: 'email@mail.com')
77
77
 
78
78
  We want to provide full compatibility with existing `validates_uniqueness_of` validator.
79
79
 
80
- This list of supported options from `validates_uniqueness_of` validator:
80
+ 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").
@@ -88,16 +88,21 @@ This list of supported options from `validates_uniqueness_of` validator:
88
88
  validates_db_uniqueness_of :email
89
89
  ```
90
90
 
91
- Is the same by default as following
91
+ Is the same by default as the following
92
92
 
93
93
  ```ruby
94
94
  validates_uniqueness_of :email, allow_nil: true, allow_blank: false, case_sensitive: true
95
95
  ```
96
96
 
97
+ List of supported options for `PostgreSQL` only:
98
+
99
+ - `where`: Specify the conditions to be included as a <tt>WHERE</tt> SQL fragment to
100
+ limit the uniqueness constraint lookup (e.g. <tt>where: "(status = 'active')"</tt>).
101
+ For backward compatibility, this will be converted automatically
102
+ to <tt>conditions: -> { where("(status = 'active')") }</tt> for `valid?` method.
103
+
97
104
  The list of options to add support:
98
105
 
99
- - `conditions`: Specify the conditions to be included as a <tt>WHERE</tt> SQL fragment to
100
- limit the uniqueness constraint lookup (e.g. <tt>conditions: -> { where(status: 'active') }</tt>).
101
106
  - `case_sensitive`: Looks for an exact match. Ignored by non-text columns (`true` by default).
102
107
  - `allow_nil`: If set to `true`, skips this validation if the attribute is `nil` (default is `false`).
103
108
  - `allow_blank`: If set to `true`, skips this validation if the attribute is blank (default is `false`).
@@ -12,8 +12,8 @@ module DatabaseValidations
12
12
  indexes.find { |index| index.name == index_name }
13
13
  end
14
14
 
15
- def find_index_by_columns(index_columns)
16
- indexes.find { |index| index.columns.map(&:to_s).sort == index_columns }
15
+ def find_index(columns, where)
16
+ indexes.find { |index| index.columns.map(&:to_s).sort == columns && index.where == where }
17
17
  end
18
18
 
19
19
  def indexes
@@ -1,7 +1,7 @@
1
1
  module DatabaseValidations
2
2
  module Adapters
3
3
  class PostgresqlAdapter < BaseAdapter
4
- SUPPORTED_OPTIONS = %i[scope message].freeze
4
+ SUPPORTED_OPTIONS = %i[scope message where].freeze
5
5
  ADAPTER = :postgresql
6
6
 
7
7
  def error_columns(error_message)
@@ -3,14 +3,22 @@ module DatabaseValidations
3
3
  class Base < StandardError; end
4
4
 
5
5
  class IndexNotFound < Base
6
- attr_reader :columns
6
+ attr_reader :columns, :where_clause, :available_indexes
7
7
 
8
- def initialize(columns)
8
+ def initialize(columns, where_clause, available_indexes)
9
9
  @columns = columns.map(&:to_s)
10
- super "No unique index found with columns: #{self.columns}. "\
10
+ @where_clause = where_clause
11
+ @available_indexes = available_indexes
12
+
13
+ super "No unique index found with #{columns_and_where_text(columns, where_clause)}. "\
14
+ "Available indexes are: [#{self.available_indexes.map { |ind| columns_and_where_text(ind.columns, ind.where) }.join(', ')}]. "\
11
15
  "Use ENV['SKIP_DB_UNIQUENESS_VALIDATOR_INDEX_CHECK']=true in case you want to skip the check. "\
12
16
  "For example, when you run migrations."
13
17
  end
18
+
19
+ def columns_and_where_text(columns, where)
20
+ "columns: #{columns}#{" and where: #{where}" if where}"
21
+ end
14
22
  end
15
23
 
16
24
  class UnknownDatabase < Base
@@ -6,7 +6,6 @@ module DatabaseValidations
6
6
  key = generate_key(Adapters.factory(instance.class).error_columns(error.message))
7
7
 
8
8
  each_options_storage(instance.class) do |storage|
9
- # storage has this then return
10
9
  return storage[key].handle_unique_error(instance) if storage[key]
11
10
  end
12
11
 
@@ -10,14 +10,18 @@ module DatabaseValidations
10
10
  end
11
11
 
12
12
  def handle_unique_error(instance)
13
- error_options = options.except(:case_sensitive, :scope, :conditions, :attributes)
13
+ error_options = options.except(:case_sensitive, :scope, :conditions, :attributes, :where)
14
14
  error_options[:value] = instance.public_send(options[:attributes])
15
15
 
16
16
  instance.errors.add(options[:attributes], :taken, error_options)
17
17
  end
18
18
 
19
19
  def validates_uniqueness_options
20
- options.merge(allow_nil: true, case_sensitive: true, allow_blank: false)
20
+ where_clause_str = where_clause
21
+
22
+ options.except(:where)
23
+ .merge(allow_nil: true, case_sensitive: true, allow_blank: false)
24
+ .tap { |opts| opts[:conditions] = -> { where(where_clause_str) } if where_clause }
21
25
  end
22
26
 
23
27
  def key
@@ -28,6 +32,10 @@ module DatabaseValidations
28
32
  @columns ||= Helpers.unify_columns(field, Array.wrap(options[:scope]))
29
33
  end
30
34
 
35
+ def where_clause
36
+ @where_clause ||= options[:where]
37
+ end
38
+
31
39
  def raise_if_unsupported_options!
32
40
  options.except(:attributes).each_key do |option|
33
41
  unless adapter.support_option?(option)
@@ -37,7 +45,7 @@ module DatabaseValidations
37
45
  end
38
46
 
39
47
  def raise_if_index_missed!
40
- raise Errors::IndexNotFound.new(columns) unless adapter.find_index_by_columns(columns)
48
+ raise Errors::IndexNotFound.new(columns, where_clause, adapter.indexes) unless adapter.find_index(columns, where_clause)
41
49
  end
42
50
 
43
51
  private
@@ -1,3 +1,3 @@
1
1
  module DatabaseValidations
2
- VERSION = "0.3.7"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: database_validations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgeniy Demin