Shoulda-matchers: Check for belongs_to asks for explicit "required: true" when using before_validation

Created on 8 Nov 2018  路  7Comments  路  Source: thoughtbot/shoulda-matchers

rails version

5.1+

shoulda-matchers version

gem 'shoulda-matchers', '4.0.0.rc1'

Error

  1) Employee should belong to manager required: true
     Failure/Error: it { should belong_to(:manager) }
       Expected Employee to have a belongs_to association called manager (the association should have been defined with `required: true`, but was not)
     # ./spec/models/employee_spec.rb:4:in `block (2 levels) in <top (required)>'

Steps to reproduce

class Manager < ApplicationRecord
  has_many :employees
end
class Employee < ApplicationRecord
  belongs_to :manager

  before_validation :add_manager

  def add_manager
    self.manager = Manager.create
  end
end
require 'rails_helper'

RSpec.describe Employee, type: :model do
  it { should belong_to(:manager) }
end

Note

It continues to happen if I set the required: true

Bug 馃 Needs Decision

Most helpful comment

I've added a new without_validating_presence qualifier to belong_to to address cases like these, and that will be available in 4.0. Docs here: https://github.com/thoughtbot/shoulda-matchers/blob/707d87dbd60d2b1781f4ea2e9dab73e207d65173/lib/shoulda/matchers/active_record/association_matcher.rb#L275-L302

All 7 comments

Hey @mccard. Thanks for the detailed report and sorry it took so long for me to get back to you on this.

The reason why the matcher is failing is that your manager association is always being set. A presence validation is being added automatically by the matcher, but the matcher is confused because it expects a new instance of Employee to fail validation if manager is not set.

I think I mentioned this in another issue, but I'm wondering now if I need to add an additional qualifier that tells the matcher not to worry about the presence validation check. Something like should belong_to(:manager).without_validating_presence. Or, perhaps even automatically checking for a presence validation is the wrong move here. I'll have to think more about this.

What about unsetting the association before running the presence validation? I can provide a PR if that would be useful.

@johnam Yup, that's what the matcher is doing already. The problem is that no matter how the matcher changes the association, the model is overwriting it before the presence validation gets run.

I've added a new without_validating_presence qualifier to belong_to to address cases like these, and that will be available in 4.0. Docs here: https://github.com/thoughtbot/shoulda-matchers/blob/707d87dbd60d2b1781f4ea2e9dab73e207d65173/lib/shoulda/matchers/active_record/association_matcher.rb#L275-L302

Sorry for my English. When I tries use without_presence_validation i have exception
undefined method 'without_presence_validation' for #<Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher:0x0000557e5e4f29c8>

in Gemfile.lock using shoulda-matchers 4.3.0

Sorry. I use without_presence_validation instead without_validating_presence

@vesh95 It looks like you're using without_presence_validation on validate_presence_of. You will probably want to use it on belong_to.

Was this page helpful?
0 / 5 - 0 ratings