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

Account for composite primary key in foreign key #1396

Merged
merged 1 commit into from Jan 14, 2021

Conversation

natematykiewicz
Copy link
Contributor

Fixes [#1392]

@natematykiewicz
Copy link
Contributor Author

@vsppedro what do you think of this?

Things get a little weird in symbols vs strings. When options[:foreign_key] fails, the value you passed in is used as-is. If that succeeds and it looks up the actual foreign_key, the value is normalized to a string (though, I stopped it from turning [:a, :b] into a string of "[:a, :b]" and instead turned it into ["a", "b"]).

I think it solves the problem, though it looks like primary key has the same original issue (no error message in the options check). I also think some DRYing could happen here between primary and foreign key checks.

I'm also not really sure what level of support is expected for Composite Primary Keys. shoulda-matchers doesn't mention that it supports CPK, but it also did work until the most recent version.

I'm open to any and all feedback. One thing that's nice here is that it actually asserts that the configured foreign key's corresponding column(s) exist when passing in an option. This is a nice additional check that it wasn't doing in 4.4.0. It would be good to do the same for the primary key in a future PR.

@vsppedro
Copy link
Collaborator

I should have asked if you would like to make the contribution. I'm sorry.

Thank you very much!

LGTM!

@natematykiewicz
Copy link
Contributor Author

You're totally fine!

@vsppedro
Copy link
Collaborator

vsppedro commented Jan 13, 2021

I also think some DRYing could happen here between primary and foreign key checks.

I agree with you, but I think we can do that on another PR later. Let's fix this first. 👍

@vsppedro
Copy link
Collaborator

@mcmire, what do you think of this?

I'm thinking of releasing a fix for this - v4.5.1.

Copy link
Collaborator

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me!

@vsppedro
Copy link
Collaborator

Thanks! Merging!

@vsppedro vsppedro merged commit f7061a7 into thoughtbot:master Jan 14, 2021
@natematykiewicz natematykiewicz deleted the fix_fk_cpk-patch1 branch January 14, 2021 22:46
@vsppedro vsppedro mentioned this pull request Jan 15, 2021
@vsppedro
Copy link
Collaborator

Hi @natematykiewicz, I'm sending this message just to let you know that we now have a new version of SholdaMatchers with your contribution! Thank you again!

@natematykiewicz
Copy link
Contributor Author

I just upgraded. Everything works and the additional testing showed me that I had an incorrect :inverse_of on an association. 😬 Thanks for this!

@voxik
Copy link
Contributor

voxik commented Feb 9, 2021

Just FTR, I think there is something about the symbol vs strings, because testing against Rails 6.1, there are two test failures:

  1) Shoulda::Matchers::ActiveRecord::AssociationMatcher have_one rejects an association with a valid :class_name and :foreign_key option (CPK), but no columns
     Failure/Error:
       expect do
         have_one(:detail).class_name('PersonDetail').
           with_foreign_key(%i[company_id person_detail_id])
       end.not_to match_against(Person.new).and_fail_with(expected_message)
     
       Expected the positive version of the matcher not to match and for the failure
       message to be:
     
       ------------------------------------------------------------------------
       Expected Person to have a has_one association called detail (PersonDetail does not have a ["company_id", "person_detail_id"] foreign key.)
       ------------------------------------------------------------------------
     
       However, it was:
     
       ------------------------------------------------------------------------
       Expected Person to have a has_one association called detail (PersonDetail does not have a [:company_id, :person_detail_id] foreign key.)
       ------------------------------------------------------------------------
     
       Diff:
     # ./spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb:1455:in `block (3 levels) in <top (required)>'
     # /usr/share/gems/gems/bundler-2.2.3/libexec/bundle:49:in `block in <top (required)>'
     # /usr/share/gems/gems/bundler-2.2.3/libexec/bundle:37:in `<top (required)>'

  2) Shoulda::Matchers::ActiveRecord::AssociationMatcher have_one accepts an association with a valid :class_name and :foreign_key option (CPK)
     Failure/Error:
       expect(Person.new).
         to have_one(:detail).
         class_name('PersonDetail').
         with_foreign_key(%i[company_id person_detail_id])
     
       Expected Person to have a has_one association called detail (PersonDetail does not have a [:company_id, :person_detail_id] foreign key.)
     # ./spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb:1467:in `block (3 levels) in <top (required)>'
     # /usr/share/gems/gems/bundler-2.2.3/libexec/bundle:49:in `block in <top (required)>'
     # /usr/share/gems/gems/bundler-2.2.3/libexec/bundle:37:in `<top (required)>'

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

Successfully merging this pull request may close these issues.

None yet

4 participants