Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check for belongs_to asks for explicit "required: true" when using before_validation #1154

Closed
matheus-cardoso-deel opened this issue Nov 8, 2018 · 7 comments

Comments

@matheus-cardoso-deel
Copy link

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

@mcmire mcmire added this to the v4.0 milestone Nov 11, 2018
@mcmire
Copy link
Collaborator

mcmire commented Dec 28, 2018

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.

@johnam
Copy link

johnam commented Jan 13, 2019

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

@mcmire
Copy link
Collaborator

mcmire commented Jan 13, 2019

@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.

@mcmire
Copy link
Collaborator

mcmire commented Feb 15, 2019

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:

# #### without_presence_validation
#
# Use `without_presence_validation` with `belong_to` to prevent the
# matcher from checking whether the association disallows nil (Rails 5+
# only). This can be helpful if you have a custom hook that always sets
# the association to a meaningful value:
#
# class Person < ActiveRecord::Base
# belongs_to :organization
#
# before_validation :autoassign_organization
#
# private
#
# def autoassign_organization
# self.organization = Organization.create!
# end
# end
#
# # RSpec
# describe Person
# it { should belong_to(:organization).without_presence_validation }
# end
#
# # Minitest (Shoulda)
# class PersonTest < ActiveSupport::TestCase
# should belong_to(:organization).without_presence_validation
# end

@mcmire mcmire closed this as completed Feb 15, 2019
@vesh95
Copy link

vesh95 commented Apr 1, 2020

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

@vesh95
Copy link

vesh95 commented Apr 1, 2020

Sorry. I use without_presence_validation instead without_validating_presence

@mcmire
Copy link
Collaborator

mcmire commented Apr 1, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants