Closed gnilrets closed 4 years ago
Okay, can you re-run these tests with the --backtrace
option?
Failures:
1) JobSpec should ensure inclusion of job_template_type in ["TplBirstSoapGenericCommand", "TplBirstDuplicateSpace"]
Failure/Error: it { should ensure_inclusion_of(:job_template_type).in_array(JobSpec::JOB_TEMPLATE_TYPES) }
NameError:
wrong constant name shouldamatchersteststring
# ./vendor/gems/activesupport-4.1.4/lib/active_support/inflector/methods.rb:238:in `const_get'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/inflector/methods.rb:238:in `block in constantize'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/inflector/methods.rb:236:in `each'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/inflector/methods.rb:236:in `inject'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/inflector/methods.rb:236:in `constantize'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/core_ext/string/inflections.rb:66:in `constantize'
# ./vendor/gems/activerecord-4.1.4/lib/active_record/associations/belongs_to_polymorphic_association.rb:7:in `klass'
# ./vendor/gems/activerecord-4.1.4/lib/active_record/associations/belongs_to_association.rb:37:in `find_target?'
# ./vendor/gems/activerecord-4.1.4/lib/active_record/associations/association.rb:138:in `load_target'
# ./vendor/gems/activerecord-4.1.4/lib/active_record/associations/association.rb:53:in `reload'
# ./vendor/gems/activerecord-4.1.4/lib/active_record/associations/singular_association.rb:9:in `reader'
# ./vendor/gems/activerecord-4.1.4/lib/active_record/autosave_association.rb:287:in `validate_single_association'
# ./vendor/gems/activerecord-4.1.4/lib/active_record/autosave_association.rb:209:in `block in add_autosave_association_callbacks'
# ./vendor/gems/activerecord-4.1.4/lib/active_record/autosave_association.rb:157:in `instance_eval'
# ./vendor/gems/activerecord-4.1.4/lib/active_record/autosave_association.rb:157:in `block in define_non_cyclic_method'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:424:in `block in make_lambda'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:184:in `call'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:184:in `block in simple'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:185:in `call'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:185:in `block in simple'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:185:in `call'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:185:in `block in simple'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:185:in `call'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:185:in `block in simple'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:86:in `call'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:86:in `run_callbacks'
# ./vendor/gems/activemodel-4.1.4/lib/active_model/validations.rb:376:in `run_validations!'
# ./vendor/gems/activemodel-4.1.4/lib/active_model/validations/callbacks.rb:111:in `block in run_validations!'
# ./vendor/gems/activesupport-4.1.4/lib/active_support/callbacks.rb:82:in `run_callbacks'
# ./vendor/gems/activemodel-4.1.4/lib/active_model/validations/callbacks.rb:111:in `run_validations!'
# ./vendor/gems/activemodel-4.1.4/lib/active_model/validations.rb:317:in `valid?'
# ./vendor/gems/activerecord-4.1.4/lib/active_record/validations.rb:70:in `valid?'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/validation_message_finder.rb:61:in `validate_instance'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/validation_message_finder.rb:57:in `validated_instance'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/validation_message_finder.rb:53:in `errors'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/validation_message_finder.rb:23:in `has_messages?'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/allow_value_matcher.rb:256:in `has_messages?'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/allow_value_matcher.rb:252:in `errors_match?'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/allow_value_matcher.rb:222:in `block in matches?'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/allow_value_matcher.rb:219:in `each
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/allow_value_matcher.rb:219:in `each'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/allow_value_matcher.rb:219:in `none?'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/allow_value_matcher.rb:219:in `matches?'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/validation_matcher.rb:43:in `allows_value_of'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb:388:in `disallows_value_outside_of_array?'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb:326:in `matches_for_array?'
# ./vendor/gems/shoulda-matchers-2.6.2/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb:304:in `matches?'
# ./vendor/gems/rspec-expectations-3.0.4/lib/rspec/expectations/handler.rb:48:in `handle_matcher'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/memoized_helpers.rb:81:in `should'
# ./spec/models/job_spec_spec.rb:20:in `block (2 levels) in <top (required)>'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example.rb:148:in `instance_exec'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example.rb:148:in `block in run'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example.rb:210:in `call'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example.rb:210:in `block (2 levels) in <class:Procsy>'
# ./vendor/gems/rspec-rails-3.0.2/lib/rspec/rails/adapters.rb:72:in `block (2 levels) in <module:MinitestLifecycleAdapter>'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example.rb:294:in `instance_exec'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example.rb:294:in `instance_exec'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/hooks.rb:430:in `block (2 levels) in run'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example.rb:210:in `call'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example.rb:210:in `block (2 levels) in <class:Procsy>'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/hooks.rb:432:in `run'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/hooks.rb:485:in `run'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example.rb:303:in `with_around_example_hooks'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example.rb:145:in `run'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example_group.rb:494:in `block in run_examples'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example_group.rb:490:in `map'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example_group.rb:490:in `run_examples'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/example_group.rb:457:in `run'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/runner.rb:112:in `block (2 levels) in run_specs'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/runner.rb:112:in `map'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/runner.rb:112:in `block in run_specs'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/reporter.rb:54:in `report'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/runner.rb:108:in `run_specs'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/runner.rb:86:in `run'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/runner.rb:70:in `run'
# ./vendor/gems/rspec-core-3.0.4/lib/rspec/core/runner.rb:38:in `invoke'
# ./vendor/gems/rspec-core-3.0.4/exe/rspec:4:in `<top (required)>'
# ./vendor/bin/rspec:23:in `load'
# ./vendor/bin/rspec:23:in `<main>'
Ah. So it looks like it's failing because the attribute in question is polymorphic and thus ActiveRecord expects any value for this attribute to be a known class. I'll mark this as a bug, but in the meantime you can use allow_value
to get around this:
it { should allow_value(JobSpec::JOB_TEMPLATE_TYPES).for(:job_template_type) }
it do
all_other_models = ActiveRecord::Base.subclasses.map(&:to_s) - JobSpec::JOB_TEMPLATE_TYPES
should_not allow_value(*all_other_models).for(:job_template_type)
end
Using Ruby 2.1.5, Rails 4.2.0, and Shoulda-Matchers 2.8.0, shoulda-matchers also fails trying to validate_inclusion_of [:user] for resource_type in the popular 'rolify' gem. The Role class:
class Role < ActiveRecord::Base has_and_belongs_to_many :users, join_table: :users_roles belongs_to :resource, polymorphic: true validates :resource_type, inclusion: { in: [:user] }, allow_nil: true scopify end
My attempted validation of validates_inclusion_of(:resource_type): it { should validate_inclusion_of(:resource_type).in_array([nil, "user"]) }
The error message I get (it doesn't matter whether or not I include nil in the array): Failures: 1) Role should ensure inclusion of resource_type in [nil, "user"] Failure/Error: it { should validate_inclusion_of(:resource_type).in_array([nil, "user"]) } [nil, "user"] doesn't match array in validation
(If I use only ["user"], the error I get is the expected ["user"] doesn't match array in validation)
I added some puts in the shoulda-matcher code to try to figure out what was going on: allows_all_values_in_array @array = [nil, "user"] allows_all_values_in_array: @low_message = nil allows_all_values_in_array: true, , allows_all_values_in_array: @low_message = nil allows_all_values_in_array: false, user, matches_for_array: false true true true
(If I use only ["user"], the output is: allows_all_values_in_array @array = ["user"] allows_all_values_in_array: @low_message = nil allows_all_values_in_array: false, user, matches_for_array: false true true true)
My next attempted validation using allows_value doesn't work either: Failures: 1) Role should allow resource_type to be set to "user" Failure/Error: it { should allow_value("user").for(:resource_type) } Did not expect errors when resource_type is set to "user", got errors: * "is not included in the list" (attribute: resource_type, value: "user")
(Note that "Role should allow resource_type to be set to nil" does validate correctly, as would be expected from the output above.)
@cindyward1 Doesn't resource_type
take the name of a class as a value, and not a symbol? What if you say:
validates :resource_type, inclusion: { in: ['User'] }, allow_nil: true
and then to test it:
should validate_inclusion_of(:resource_type).in_array('User').allow_nil
What you sent me works fine and explains why resource_type is always NULL in my development database. I misunderstood how to modify the Role class. Thanks for finding my bug ... Cindy
On Tuesday, February 17, 2015 9:18 AM, Elliot Winkler <notifications@github.com> wrote:
@cindyward1 Doesn't resource_type take the name of a class as a value, and not a symbol? What if you say:validates :resource_type, inclusion: { in: ['User'] }, allow_nil: trueand then to test it:should validate_inclusion_of(:resource_type).in_array('User').allow_nil — Reply to this email directly or view it on GitHub.
Try this , It's works for me it do should validate_inclusion_of(:resource_type) .in_array(Rolify.resource_types) .allow_nil(true) end
@mcmire I think I'm hitting this issue as well. I'm using ruby v2.4.1, rails v5.1.4 and shoulda-matchers v3.1.2
class Favourite < ApplicationRecord
belongs_to :user
belongs_to :favourable, polymorphic: true
validates_presence_of :user_id, :favourable_id, :favourable_type
validates :favourable_type, inclusion: { in: %w[Project],
message: "%{value} can't be favourited" }
Rspec tests:
context 'validation' do
let!(:user) { create(:user) }
let!(:project) { create(:project) }
let!(:favourite_project) { user.favourites.build(favourable: project) }
context 'favourable type' do
specify 'valid type' do
expect(favourite_project).to validate_inclusion_of(:favourable_type)
.in_array(%w[Project])
end
end
end
Error thrown:
NameError:
wrong constant name shoulda-matchers test string
@amnesia7 Cool, thanks for reporting this :) This is definitely something we need help fixing.
Let me know if you need any more info or need anything testing, or if there's anything straight forward that I can help with to get this resolved.
Col
On Thu, 26/10/17, Elliot Winkler notifications@github.com wrote:
Subject: Re: [thoughtbot/shoulda-matchers] ensure_inclusion_of does not work with polymorphic attributes (#574) To: "thoughtbot/shoulda-matchers" shoulda-matchers@noreply.github.com Cc: "amnesia7" col.gibson@gmail.com, "Mention" mention@noreply.github.com Date: Thursday, 26 October, 2017, 21:12
@amnesia7 Cool, thanks for reporting this :) This is definitely something we need help fixing.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
Still present in 2019. Will see if I can help.
Hey folks. In an effort to lighten our load as maintainers and be able to serve you better in the future, the shoulda-matchers team is working on cleaning out the cobwebs in this repo by pruning the backlog. As there are few of us, there are a lot of items that will simply never earn our attention in a reasonable time frame, and rather than giving you an empty promise, we think it makes more sense to focus on more recent issues. That means, unfortunately, that we must close this issue.
Don't take this the wrong way: our aim is not to diminish the effort people have made or dismiss problems that have been raised. If you feel that we should reopen this issue, then please let us know so that we can reprioritize it. Thanks!
Any update regarding this issue?
No update, but if you can come up with a fix for this then we'd be happy to merge it in!
If you're testing a lot of models with polymorphic associations, you can use rspec helpers to DRY things up a bit:
# spec/support/model_helpers.rb
module ModelHelpers
def all_models_except(*models)
ApplicationRecord.subclasses.map(&:to_s) - models
end
end
# spec/models/your_model.rb
it { should_not allow_value(*all_models_except('Foo', 'Bar').for(:whatever_type) }
So I had
ensure_inclusion_of
working just fine, then I migrated some things to use FactoryGirl instead of explicit create statements and suddenly it's failing. If Idup
the object created by FactoryGirl, it works again. Here's an example in my spec:The first test fails, the second is successful: