diff --git a/lib/shoulda/matchers/action_controller/permit_matcher.rb b/lib/shoulda/matchers/action_controller/permit_matcher.rb index 8e8b5c48f..ef184aaf0 100644 --- a/lib/shoulda/matchers/action_controller/permit_matcher.rb +++ b/lib/shoulda/matchers/action_controller/permit_matcher.rb @@ -250,7 +250,12 @@ def matches?(controller) parameters_double_registry.register Doublespeak.with_doubles_activated do - context.__send__(verb, action, request_params) + Shoulda::Matchers::RailsShim.make_controller_request( + context, + verb, + action, + request_params, + ) end unpermitted_parameter_names.empty? diff --git a/lib/shoulda/matchers/rails_shim.rb b/lib/shoulda/matchers/rails_shim.rb index 471d9049c..1fea4eb12 100644 --- a/lib/shoulda/matchers/rails_shim.rb +++ b/lib/shoulda/matchers/rails_shim.rb @@ -2,79 +2,130 @@ module Shoulda module Matchers # @private class RailsShim - def self.verb_for_update - if action_pack_gte_4_1? - :patch - else - :put + class << self + def action_pack_gte_4_1? + Gem::Requirement.new('>= 4.1').satisfied_by?(action_pack_version) end - end - def self.type_cast_default_for(model, column) - if model.respond_to?(:column_defaults) - # Rails 4.2 - model.column_defaults[column.name] - else - column.default + def action_pack_gte_5? + Gem::Requirement.new('>= 5').satisfied_by?(action_pack_version) + end + + def action_pack_version + Gem::Version.new(::ActionPack::VERSION::STRING) + end + + def active_record_major_version + ::ActiveRecord::VERSION::MAJOR end - end - def self.serialized_attributes_for(model) - if defined?(::ActiveRecord::Type::Serialized) - # Rails 5+ - model.columns.select do |column| - model.type_for_attribute(column.name).is_a?( - ::ActiveRecord::Type::Serialized, + def generate_validation_message( + record, + attribute, + type, + model_name, + options + ) + if record && record.errors.respond_to?(:generate_message) + record.errors.generate_message(attribute.to_sym, type, options) + else + simply_generate_validation_message( + attribute, + type, + model_name, + options, ) - end.inject({}) do |hash, column| - hash[column.name.to_s] = model.type_for_attribute(column.name).coder - hash end - else - model.serialized_attributes + rescue RangeError + simply_generate_validation_message( + attribute, + type, + model_name, + options, + ) end - end - def self.generate_validation_message(record, attribute, type, model_name, options) - if record && record.errors.respond_to?(:generate_message) - record.errors.generate_message(attribute.to_sym, type, options) - else - simply_generate_validation_message(attribute, type, model_name, options) + def make_controller_request(context, verb, action, request_params) + params = + if action_pack_gte_5? + { params: request_params } + else + request_params + end + + context.__send__(verb, action, params) end - rescue RangeError - simply_generate_validation_message(attribute, type, model_name, options) - end - def self.simply_generate_validation_message(attribute, type, model_name, options) - default_translation_keys = [ - :"activerecord.errors.models.#{model_name}.#{type}", - :"activerecord.errors.messages.#{type}", - :"errors.attributes.#{attribute}.#{type}", - :"errors.messages.#{type}" - ] - primary_translation_key = :"activerecord.errors.models.#{model_name}.attributes.#{attribute}.#{type}" - translate_options = { default: default_translation_keys }.merge(options) - I18n.translate(primary_translation_key, translate_options) - end + def serialized_attributes_for(model) + if defined?(::ActiveRecord::Type::Serialized) + # Rails 5+ + serialized_columns = model.columns.select do |column| + model.type_for_attribute(column.name).is_a?( + ::ActiveRecord::Type::Serialized, + ) + end - def self.tables_and_views(connection) - if active_record_major_version >= 5 - connection.data_sources - else - connection.tables + serialized_columns.inject({}) do |hash, column| + hash[column.name.to_s] = model.type_for_attribute(column.name).coder + hash + end + else + model.serialized_attributes + end end - end - def self.active_record_major_version - ::ActiveRecord::VERSION::MAJOR - end + def type_cast_default_for(model, column) + if model.respond_to?(:column_defaults) + # Rails 4.2 + model.column_defaults[column.name] + else + column.default + end + end - def self.action_pack_gte_4_1? - Gem::Requirement.new('>= 4.1').satisfied_by?(action_pack_version) - end + def tables_and_views(connection) + if active_record_major_version >= 5 + connection.data_sources + else + connection.tables + end + end - def self.action_pack_version - Gem::Version.new(::ActionPack::VERSION::STRING) + def verb_for_update + if action_pack_gte_4_1? + :patch + else + :put + end + end + + private + + def simply_generate_validation_message( + attribute, + type, + model_name, + options + ) + default_translation_keys = [ + :"activerecord.errors.models.#{model_name}.#{type}", + :"activerecord.errors.messages.#{type}", + :"errors.attributes.#{attribute}.#{type}", + :"errors.messages.#{type}", + ] + primary_translation_key = [ + :activerecord, + :errors, + :models, + model_name, + :attributes, + attribute, + type, + ] + translate_options = + { default: default_translation_keys }.merge(options) + I18n.translate(primary_translation_key, translate_options) + end end end end diff --git a/spec/support/unit/helpers/action_pack_versions.rb b/spec/support/unit/helpers/action_pack_versions.rb new file mode 100644 index 000000000..86606f7ba --- /dev/null +++ b/spec/support/unit/helpers/action_pack_versions.rb @@ -0,0 +1,18 @@ +module UnitTests + module ActionPackVersions + extend self + + def self.configure_example_group(example_group) + example_group.include(self) + example_group.extend(self) + end + + def action_pack_gte_5? + action_pack_version =~ '>= 5' + end + + def action_pack_version + Tests::Version.new(ActionPack::VERSION::STRING) + end + end +end diff --git a/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb b/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb index 1a1a5a55b..b8857df96 100644 --- a/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb @@ -498,7 +498,12 @@ def params_with_conditional_require(params, *filters) matcher.matches?(controller) - expect(context).to have_received(:post).with(:create, {}) + expect_to_have_made_controller_request( + verb: :post, + action: :create, + params: {}, + context: context, + ) end end @@ -511,7 +516,12 @@ def params_with_conditional_require(params, *filters) matcher.matches?(controller) - expect(context).to have_received(:patch).with(:update, {}) + expect_to_have_made_controller_request( + verb: :patch, + action: :update, + params: {}, + context: context, + ) end else it 'PUTs to the controller' do @@ -521,7 +531,12 @@ def params_with_conditional_require(params, *filters) matcher.matches?(controller) - expect(context).to have_received(:put).with(:update, {}) + expect_to_have_made_controller_request( + verb: :put, + action: :update, + params: {}, + context: context, + ) end end end @@ -536,7 +551,12 @@ def params_with_conditional_require(params, *filters) matcher.matches?(controller) - expect(context).to have_received(:delete).with(:hide, {}) + expect_to_have_made_controller_request( + verb: :delete, + action: :hide, + params: {}, + context: context, + ) end end end @@ -598,4 +618,12 @@ def define_controller_raising_exception def build_context double('context', post: nil, put: nil, patch: nil, delete: nil) end + + def expect_to_have_made_controller_request(context:, verb:, action:, params:) + if action_pack_gte_5? + expect(context).to have_received(verb).with(action, params: params) + else + expect(context).to have_received(verb).with(action, params) + end + end end diff --git a/spec/unit_spec_helper.rb b/spec/unit_spec_helper.rb index ba99e6b05..dfbe21d63 100644 --- a/spec/unit_spec_helper.rb +++ b/spec/unit_spec_helper.rb @@ -10,6 +10,7 @@ end RSpec.configure do |config| + UnitTests::ActionPackVersions.configure_example_group(config) UnitTests::ActiveModelHelpers.configure_example_group(config) UnitTests::ActiveModelVersions.configure_example_group(config) UnitTests::ClassBuilder.configure_example_group(config)