Version: shoulda-matchers (4.0.0.rc1)
Given an ActiveRecord model with a uniqueness validation where the scoped_to parameter is a string (which is otherwise appears to be perfectly valid):
class Post < ApplicationRecord
validates :name, uniqueness: { scope: "account_id" }
end
And a spec:
it { is_expected.to validate_uniqueness_of(:name).scoped_to("account_id") }
I expect the validation to run, but it errors out:
Failure/Error: it { is_expected.to validate_uniqueness_of(:name).scoped_to("account_id") }
TypeError:
wrong argument type String (expected Proc)
# /Users/philcoggins/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/shoulda-matchers-4.0.0.rc1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb:843:in `block in all_scopes_are_booleans?'
# /Users/philcoggins/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/shoulda-matchers-4.0.0.rc1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb:842:in `all?'
# /Users/philcoggins/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/shoulda-matchers-4.0.0.rc1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb:842:in `all_scopes_are_booleans?'
# /Users/philcoggins/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/shoulda-matchers-4.0.0.rc1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb:762:in `matches_uniqueness_with_scopes?'
# /Users/philcoggins/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/shoulda-matchers-4.0.0.rc1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb:332:in `matches?'
# /Users/philcoggins/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.7.0/lib/rspec/expectations/handler.rb:50:in `block in handle_matcher'
# /Users/philcoggins/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.7.0/lib/rspec/expectations/handler.rb:27:in `with_matcher'
# /Users/philcoggins/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.7.0/lib/rspec/expectations/handler.rb:48:in `handle_matcher'
# /Users/philcoggins/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/rspec-expectations-3.7.0/lib/rspec/expectations/expectation_target.rb:65:in `to'
This appears to stem from the fact that arguments are expected to be symbols.
I can fix with the following monkey-patch and changing the matcher to .scoped_to(:account_id)
module Shoulda
module Matchers
module ActiveRecord
class ValidateUniquenessOfMatcher < ActiveModel::ValidationMatcher
def actual_sets_of_scopes
validations.map do |validation|
Array.wrap(validation.options[:scope]).map(&:to_sym)
end.reject(&:empty?)
end
end
end
end
end
I could also fix by simply changing the scoped_to attribute to use a symbol, but this uniqueness validation is generated in a separate library that I don't have as much control over.
Thanks for the report! We'll see if we can fix this in the next version, although a PR is welcome!
I tried this solution and getting following error
NameError: uninitialized constant ActiveModel::ValidationMatcher
Rails Version: Rails 5.2.2.1
Ruby Version: 2.5.1
shoulda-matchers: 3.1.3
@zeeshangulzar where did you add the code?
I added code in a new file under config/initializers/.
@zeeshangulzar I have mine in rails_helper.rb, underneath all my require statements. Also, I've only tested this patch with latest shoulda version 4.x, so without more info I'm not sure how much more help I can be.
@PhilCoggins Thanks for guidance. I have also moved it into rails_helper and it worked.
Closing this since the fix for this is now in master. ^