rubygem-shoulda-matchers/Add-minimal-support-For-rails-6.patch
lyn1001 12a0fa8580 fix build error
(cherry picked from commit 1a218eab759e825f9253a9d5d4b181c3771dbe54)
2022-03-04 16:50:15 +08:00

256 lines
9.8 KiB
Diff

diff -Nur a/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb
--- a/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb 2022-03-02 17:38:38.274324841 +0800
+++ b/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb 2022-03-02 17:48:15.220014811 +0800
@@ -562,7 +562,8 @@
def has_been_qualified?
@submatchers.any? do |submatcher|
- submatcher.class.parent == NumericalityMatchers
+ Shoulda::Matchers::RailsShim.parent_of(submatcher.class) ==
+ NumericalityMatchers
end
end
diff -Nur a/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb b/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb
--- a/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb 2022-03-02 17:38:38.274324841 +0800
+++ b/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb 2022-03-02 17:48:15.220014811 +0800
@@ -134,9 +134,8 @@
private
def secure_password_being_validated?
- defined?(::ActiveModel::SecurePassword) &&
- @subject.class.ancestors.include?(::ActiveModel::SecurePassword::InstanceMethodsOnActivation) &&
- @attribute == :password
+ Shoulda::Matchers::RailsShim.digestible_attributes_in(@subject).
+ include?(@attribute)
end
def disallows_and_double_checks_value_of!(value, message)
diff -Nur a/lib/shoulda/matchers/active_record/association_matcher.rb b/lib/shoulda/matchers/active_record/association_matcher.rb
--- a/lib/shoulda/matchers/active_record/association_matcher.rb 2022-03-02 17:38:38.278324908 +0800
+++ b/lib/shoulda/matchers/active_record/association_matcher.rb 2022-03-02 17:57:16.205124877 +0800
@@ -1182,13 +1182,11 @@
def class_has_foreign_key?(klass)
if options.key?(:foreign_key)
option_verifier.correct_for_string?(:foreign_key, options[:foreign_key])
+ elsif column_names_for(klass).include?(foreign_key)
+ true
else
- if klass.column_names.include?(foreign_key)
- true
- else
- @missing = "#{klass} does not have a #{foreign_key} foreign key."
- false
- end
+ @missing = "#{klass} does not have a #{foreign_key} foreign key."
+ false
end
end
@@ -1226,6 +1224,11 @@
def submatchers_match?
failing_submatchers.empty?
end
+ def column_names_for(klass)
+ klass.column_names
+ rescue ::ActiveRecord::StatementInvalid
+ []
+ end
end
end
end
diff -Nur a/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb b/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb
--- a/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb 2022-03-02 17:38:38.278324908 +0800
+++ b/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb 2022-03-02 17:48:15.224014878 +0800
@@ -502,10 +502,11 @@
end
def ensure_secure_password_set(instance)
- if has_secure_password?
- instance.password = "password"
- instance.password_confirmation = "password"
- end
+ Shoulda::Matchers::RailsShim.digestible_attributes_in(instance).
+ each do |attribute|
+ instance.send("#{attribute}=", 'password')
+ instance.send("#{attribute}_confirmation=", 'password')
+ end
end
def update_existing_record!(value)
@@ -529,9 +530,7 @@
end
def has_secure_password?
- model.ancestors.map(&:to_s).include?(
- 'ActiveModel::SecurePassword::InstanceMethodsOnActivation'
- )
+ Shoulda::Matchers::RailsShim.has_secure_password?(subject, @attribute)
end
def build_new_record
diff -Nur a/lib/shoulda/matchers/rails_shim.rb b/lib/shoulda/matchers/rails_shim.rb
--- a/lib/shoulda/matchers/rails_shim.rb 2022-03-02 17:38:38.274324841 +0800
+++ b/lib/shoulda/matchers/rails_shim.rb 2022-03-02 17:48:15.224014878 +0800
@@ -107,6 +107,43 @@
end
end
+ def parent_of(mod)
+ if mod.respond_to?(:module_parent)
+ mod.module_parent
+ else
+ mod.parent
+ end
+ end
+
+ def has_secure_password?(record, attribute_name)
+ if secure_password_module
+ attribute_name == :password &&
+ record.class.ancestors.include?(secure_password_module)
+ else
+ record.respond_to?("authenticate_#{attribute_name}")
+ end
+ end
+
+ def digestible_attributes_in(record)
+ record.methods.inject([]) do |array, method_name|
+ match = method_name.to_s.match(
+ /\A(\w+)_(?:confirmation|digest)=\Z/,
+ )
+
+ if match
+ array.concat([match[1].to_sym])
+ else
+ array
+ end
+ end
+ end
+
+ def secure_password_module
+ ::ActiveModel::SecurePassword::InstanceMethodsOnActivation
+ rescue NameError
+ nil
+ end
+
private
def simply_generate_validation_message(
diff -Nur a/spec/support/unit/helpers/class_builder.rb b/spec/support/unit/helpers/class_builder.rb
--- a/spec/support/unit/helpers/class_builder.rb 2022-03-02 17:38:38.270324774 +0800
+++ b/spec/support/unit/helpers/class_builder.rb 2022-03-02 17:48:15.224014878 +0800
@@ -18,18 +18,15 @@
end
def reset
- remove_defined_classes
+ remove_defined_modules
+ defined_modules.clear
end
def define_module(module_name, &block)
module_name = module_name.to_s.camelize
+ namespace, name_without_namespace = parse_constant_name(module_name)
- namespace, name_without_namespace =
- ClassBuilder.parse_constant_name(module_name)
-
- if namespace.const_defined?(name_without_namespace, false)
- namespace.__send__(:remove_const, name_without_namespace)
- end
+ remove_defined_module(module_name)
eval <<-RUBY
module #{namespace}::#{name_without_namespace}
@@ -38,6 +35,7 @@
namespace.const_get(name_without_namespace).tap do |constant|
constant.unloadable
+ @_defined_modules = defined_modules | [constant]
if block
constant.module_eval(&block)
@@ -47,13 +45,9 @@
def define_class(class_name, parent_class = Object, &block)
class_name = class_name.to_s.camelize
+ namespace, name_without_namespace = parse_constant_name(class_name)
- namespace, name_without_namespace =
- ClassBuilder.parse_constant_name(class_name)
-
- if namespace.const_defined?(name_without_namespace, false)
- namespace.__send__(:remove_const, name_without_namespace)
- end
+ remove_defined_module(class_name)
eval <<-RUBY
class #{namespace}::#{name_without_namespace} < ::#{parent_class}
@@ -62,6 +56,7 @@
namespace.const_get(name_without_namespace).tap do |constant|
constant.unloadable
+ @_defined_modules = defined_modules | [constant]
if block
if block.arity == 0
@@ -82,8 +77,21 @@
private
- def remove_defined_classes
- ::ActiveSupport::Dependencies.clear
+ def remove_defined_modules
+ defined_modules.reverse_each { |mod| remove_defined_module(mod.name) }
+ ActiveSupport::Dependencies.clear
+ end
+
+ def remove_defined_module(module_name)
+ namespace, name_without_namespace = parse_constant_name(module_name)
+
+ if namespace.const_defined?(name_without_namespace, false)
+ namespace.__send__(:remove_const, name_without_namespace)
+ end
+ end
+
+ def defined_modules
+ @_defined_modules ||= []
end
end
end
diff -Nur a/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb b/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb
--- a/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb 2022-03-02 17:38:38.262324640 +0800
+++ b/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb 2022-03-02 18:04:41.336620792 +0800
@@ -1,20 +1,18 @@
require 'unit_spec_helper'
describe Shoulda::Matchers::ActiveModel::HaveSecurePasswordMatcher, type: :model do
- if active_model_3_1?
- it 'matches when the subject configures has_secure_password with default options' do
- working_model = define_model(:example, password_digest: :string) { has_secure_password }
- expect(working_model.new).to have_secure_password
- end
+ it 'matches when the subject configures has_secure_password with default options' do
+ working_model = define_model(:example, password_digest: :string) { has_secure_password }
+ expect(working_model.new).to have_secure_password
+ end
- it 'does not match when the subject does not authenticate a password' do
- no_secure_password = define_model(:example)
- expect(no_secure_password.new).not_to have_secure_password
- end
+ it 'does not match when the subject does not authenticate a password' do
+ no_secure_password = define_model(:example)
+ expect(no_secure_password.new).not_to have_secure_password
+ end
- it 'does not match when the subject is missing the password_digest attribute' do
- no_digest_column = define_model(:example) { has_secure_password }
- expect(no_digest_column.new).not_to have_secure_password
- end
+ it 'does not match when the subject is missing the password_digest attribute' do
+ no_digest_column = define_model(:example) { has_secure_password }
+ expect(no_digest_column.new).not_to have_secure_password
end
end