database_validations 0.9.3 → 1.1.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: 37040902b8f9dd94cbfcc1785129eff2ac2f75eb085f567299852a03f4a83cfa
4
- data.tar.gz: c6a2a3331225b8344c23244692296a982ed25405be15650c32bc0815e227c20a
3
+ metadata.gz: d4f713f4e6cffee98b4e7825fa18de17fdd25780659d0bea75f8fbc90ada6ecd
4
+ data.tar.gz: 73d3f1d54aaea77a61fbc3fcb221348be0ffcb6430eaeec98c09d6cd1e4ca9a7
5
5
  SHA512:
6
- metadata.gz: 27f9f74a6f081f343bbe94da77956cd0c06419dcf321d2576a6238f0b2bddb5dd967861deaffe88ab47929e4b3837825fc9c17bf95b4fba83f5fbfd4b07d04e0
7
- data.tar.gz: 86f379332348da451c1f2d02e3e4096e528f9e00c25f10fdb8881512d97c10ffdf9ab5cffdc3f4e9ce6ea475e0d3d0a0d75b728fed700f7606ccf07cacfe9bdf
6
+ metadata.gz: 84927dd603f9f8bf8de7fbe98b5414e40de5c30f3d6adb95f5e1c77eef85c8fb7caef58c618e70ce3272feb6407cba159ce36b294d871eb793b30042b3bc5c28
7
+ data.tar.gz: b51be17960b5f2ad13ca0c6e128dc3352d5bfc53b94ecd1ea40edf1448da300ba546cf1c94e8965b839f29ea693bb1369a4bee7b1ba92f90e7d256544eec906c
@@ -9,18 +9,25 @@ module DatabaseValidations
9
9
  end
10
10
 
11
11
  # @param [String] index_name
12
- def find_index_by_name(index_name)
13
- indexes.find { |index| index.name == index_name }
12
+ def find_unique_index_by_name(index_name)
13
+ unique_indexes.find { |index| index.name == index_name }
14
14
  end
15
15
 
16
16
  # @param [Array<String>] columns
17
17
  # @param [String] where
18
- def find_index(columns, where)
19
- indexes.find { |index| Array.wrap(index.columns).map(&:to_s).sort == columns && index.where == where }
18
+ def find_unique_index(columns, where)
19
+ unique_indexes.find { |index| Array.wrap(index.columns).map(&:to_s).sort == columns && index.where == where }
20
20
  end
21
21
 
22
- def indexes
23
- model.connection.indexes(model.table_name).select(&:unique)
22
+ def unique_indexes
23
+ connection = model.connection
24
+
25
+ if connection.schema_cache.respond_to?(:indexes)
26
+ # Rails 6 only
27
+ connection.schema_cache.indexes(model.table_name).select(&:unique)
28
+ else
29
+ connection.indexes(model.table_name).select(&:unique)
30
+ end
24
31
  end
25
32
 
26
33
  def foreign_keys
@@ -8,7 +8,13 @@ module DatabaseValidations
8
8
  module_function
9
9
 
10
10
  def factory(model)
11
- case (database = model.connection_config[:adapter].downcase.to_sym)
11
+ database = if ActiveRecord.version < Gem::Version.new('6.1.0')
12
+ model.connection_config[:adapter].downcase.to_sym
13
+ else
14
+ model.connection_db_config.adapter.downcase.to_sym
15
+ end
16
+
17
+ case database
12
18
  when SqliteAdapter::ADAPTER then SqliteAdapter
13
19
  when PostgresqlAdapter::ADAPTER then PostgresqlAdapter
14
20
  when MysqlAdapter::ADAPTER then MysqlAdapter
@@ -38,8 +38,8 @@ module DatabaseValidations
38
38
 
39
39
  validator.attributes.map do |attribute|
40
40
  columns = KeyGenerator.unify_columns(attribute, validator.options[:scope])
41
- index = validator.index_name ? adapter.find_index_by_name(validator.index_name.to_s) : adapter.find_index(columns, validator.where) # rubocop:disable Metrics/LineLength
42
- raise Errors::IndexNotFound.new(columns, validator.where, validator.index_name, adapter.indexes, adapter.table_name) unless index && valid_index?(columns, index) # rubocop:disable Metrics/LineLength
41
+ index = validator.index_name ? adapter.find_unique_index_by_name(validator.index_name.to_s) : adapter.find_unique_index(columns, validator.where) # rubocop:disable Metrics/LineLength
42
+ raise Errors::IndexNotFound.new(columns, validator.where, validator.index_name, adapter.unique_indexes, adapter.table_name) unless index && valid_index?(columns, index) # rubocop:disable Metrics/LineLength
43
43
  end
44
44
  end
45
45
  end
@@ -2,19 +2,19 @@ module DatabaseValidations
2
2
  module Rescuer
3
3
  module_function
4
4
 
5
- def handled?(instance, error)
5
+ def handled?(instance, error, validate)
6
6
  Storage.prepare(instance.class) unless Storage.prepared?(instance.class)
7
7
 
8
8
  case error
9
9
  when ActiveRecord::RecordNotUnique
10
- process(instance, error, for_unique_index: :unique_index_name, for_db_uniqueness: :unique_error_columns)
10
+ process(validate, instance, error, for_unique_index: :unique_index_name, for_db_uniqueness: :unique_error_columns)
11
11
  when ActiveRecord::InvalidForeignKey
12
- process(instance, error, for_db_presence: :foreign_key_error_column)
12
+ process(validate, instance, error, for_db_presence: :foreign_key_error_column)
13
13
  else false
14
14
  end
15
15
  end
16
16
 
17
- def process(instance, error, key_types)
17
+ def process(validate, instance, error, key_types)
18
18
  adapter = Adapters.factory(instance.class)
19
19
 
20
20
  keys = key_types.map do |key_generator, error_processor|
@@ -26,14 +26,14 @@ module DatabaseValidations
26
26
 
27
27
  next unless attribute_validator
28
28
 
29
- return process_validator(instance, attribute_validator)
29
+ return process_validator(validate, instance, attribute_validator)
30
30
  end
31
31
 
32
32
  false
33
33
  end
34
34
 
35
- def process_validator(instance, attribute_validator)
36
- return false unless attribute_validator.validator.perform_db_validation?
35
+ def process_validator(validate, instance, attribute_validator)
36
+ return false unless attribute_validator.validator.perform_rescue?(validate)
37
37
 
38
38
  attribute_validator.validator.apply_error(instance, attribute_validator.attribute)
39
39
  true
@@ -22,7 +22,7 @@ module DatabaseValidations
22
22
  else
23
23
  validator.attributes.map do |attribute|
24
24
  columns = KeyGenerator.unify_columns(attribute, validator.options[:scope])
25
- index = adapter.find_index(columns, validator.where)
25
+ index = adapter.find_unique_index(columns, validator.where)
26
26
  [KeyGenerator.for_unique_index(index.name), attribute]
27
27
  end.to_h
28
28
  end
@@ -14,16 +14,21 @@ module DatabaseValidations
14
14
  end
15
15
 
16
16
  def create_or_update(*args, &block)
17
+ options = args.extract_options!
18
+ rescue_from_database_exceptions(options[:validate]) { super }
19
+ end
20
+
21
+ private
22
+
23
+ def rescue_from_database_exceptions(validate, &block)
17
24
  self._database_validations_fallback = false
18
- ActiveRecord::Base.connection.transaction(requires_new: true) { super }
25
+ self.class.connection.transaction(requires_new: true, &block)
19
26
  rescue ActiveRecord::InvalidForeignKey, ActiveRecord::RecordNotUnique => e
20
- raise e unless Rescuer.handled?(self, e)
27
+ raise e unless Rescuer.handled?(self, e, validate)
21
28
 
22
29
  raise ActiveRecord::RecordInvalid, self
23
30
  end
24
31
 
25
- private
26
-
27
32
  def perform_validations(options = {})
28
33
  options[:validate] == false || valid_without_database_validations?(options[:context])
29
34
  end
@@ -21,8 +21,8 @@ module DatabaseValidations
21
21
  Checkers::DbPresenceValidator.validate!(self)
22
22
  end
23
23
 
24
- def perform_db_validation?
25
- true
24
+ def perform_rescue?(validate)
25
+ validate != false
26
26
  end
27
27
 
28
28
  # TODO: add support of optional db_belongs_to
@@ -29,8 +29,8 @@ module DatabaseValidations
29
29
  Checkers::DbUniquenessValidator.validate!(self)
30
30
  end
31
31
 
32
- def perform_db_validation?
33
- @mode != :standard
32
+ def perform_rescue?(validate)
33
+ (validate != false && @mode != :standard) || @rescue == :always
34
34
  end
35
35
 
36
36
  def validate(record)
@@ -41,7 +41,7 @@ module DatabaseValidations
41
41
  error_options = options.except(:case_sensitive, :scope, :conditions)
42
42
  error_options[:value] = instance.public_send(attribute)
43
43
 
44
- instance.errors.add(attribute, :taken, error_options)
44
+ instance.errors.add(attribute, :taken, **error_options)
45
45
  end
46
46
 
47
47
  private
@@ -50,6 +50,7 @@ module DatabaseValidations
50
50
  @index_name = options.delete(:index_name) if options.key?(:index_name)
51
51
  @where = options.delete(:where) if options.key?(:where)
52
52
  @mode = (options.delete(:mode).presence || DEFAULT_MODE).to_sym
53
+ @rescue = (options.delete(:rescue).presence || :default).to_sym
53
54
  end
54
55
 
55
56
  def perform_query?
@@ -1,3 +1,3 @@
1
1
  module DatabaseValidations
2
- VERSION = '0.9.3'.freeze
2
+ VERSION = '1.1.0'.freeze
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.9.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgeniy Demin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-24 00:00:00.000000000 Z
11
+ date: 2021-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -208,7 +208,7 @@ homepage: https://github.com/toptal/database_validations
208
208
  licenses:
209
209
  - MIT
210
210
  metadata: {}
211
- post_install_message:
211
+ post_install_message:
212
212
  rdoc_options: []
213
213
  require_paths:
214
214
  - lib
@@ -224,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
224
  version: '0'
225
225
  requirements: []
226
226
  rubygems_version: 3.0.8
227
- signing_key:
227
+ signing_key:
228
228
  specification_version: 4
229
229
  summary: Provide compatibility between database constraints and ActiveRecord validations
230
230
  with better performance and consistency.