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

[Fix #51044] Deprecate providing a non-boolean argument to #distinct #51045

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

joshuay03
Copy link
Contributor

@joshuay03 joshuay03 commented Feb 11, 2024

Motivation / Background

Fixes #51044

Detail

Updates the documented ActiveRecord::QueryMethods#distinct and undocumented ActiveRecord::QueryMethods#distinct! methods to raise an ArgumentError log a deprecation warning if given a non-boolean argument.

Additional information

None.

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one change. Changes that are unrelated should be opened in separate PRs.
  • Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • Tests are added or updated if you fix a bug or add a feature.
  • CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

@joshuay03
Copy link
Contributor Author

joshuay03 commented Feb 11, 2024

Looks like there are 2 failures in other test cases that pass a non-boolean to #distinct!. I'll wait till this question is answered before I go and update them.

Edit: Updated these to not pass a non-boolean into #dstinct!.

@joshuay03 joshuay03 force-pushed the raise-on-invalid-distinct-args branch 6 times, most recently from 1b924d8 to 487a6ef Compare February 11, 2024 10:48
@ghiculescu
Copy link
Member

This might require a deprecation cycle since it’s a breaking change. Similar to #50931

@joshuay03 joshuay03 force-pushed the raise-on-invalid-distinct-args branch from 487a6ef to b8e6187 Compare February 12, 2024 09:50
@joshuay03
Copy link
Contributor Author

This might require a deprecation cycle since it’s a breaking change. Similar to #50931

Addressed in these changes.

@joshuay03 joshuay03 changed the title [Fix #51044] Raise an ArgumentError when providing non-boolean arguments to #distinct [Fix #51044] Deprecate providing a non-boolean argument to #distinct Feb 12, 2024
@@ -1312,6 +1312,10 @@ def distinct(value = true)

# Like #distinct, but modifies relation in place.
def distinct!(value = true) # :nodoc:
unless value == true || value == false
Copy link
Member

Choose a reason for hiding this comment

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

The deprecation should be in the public method, not the private one. Apps shouldn't call distinct! as it's nodoc'd.

That said, I'm not convinced this is worth changing. Rails and Ruby are designed to be truthy and falsey. Even if we validate this one, you're still going to have to explain to juniors or anyone new to the language what truthy/falsey means. Also in 99% of cases, anyone calling distinct is passing no value at all.

I appreciate you sending a PR, but I'm personally against making this change. Not sure if anyone else on Core feels strongly in favor.

Copy link
Member

Choose a reason for hiding this comment

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

The problem with distinct is that in SQL, distinct takes an argument which is the column you want to unique on (select distinct name from users). But in Rails it's different: User.select(:name).distinct is fine; User.distinct(:name) is wrong.

It's not surprising that (not just junior) developers forget this difference. If you agree that the Rails API is confusing, then I think it's worth doing what we can to make it less confusing.

Rails and Ruby are designed to be truthy and falsey.

I agree with this in general, but do you think there's valid exceptions (and then do you think this is one of them)?

#45229 is another example where technically any truthy argument works, but in practice there's no sensible use case for passing a value other than true or false.

Copy link
Contributor Author

@joshuay03 joshuay03 Feb 13, 2024

Choose a reason for hiding this comment

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

The deprecation should be in the public method, not the private one. Apps shouldn't call distinct! as it's nodoc'd.

I was originally raising an ArgumentError and questioned why both shouldn't be consistent, since the private method is utilised by the public method and is tested (to be specific, it had a test that passes in a non-boolean argument).

I left the check where it was when I updated to warn of a deprecation instead so that it's easier for whomever swaps it for a raise in 7.1.3 to just update the one line, which will raise an error in both methods as I had it before.

I'm happy to move it to just the public method if we also don't want the private method to raise in 7.1.3.

@joshuay03 joshuay03 force-pushed the raise-on-invalid-distinct-args branch from b8e6187 to 9da87fb Compare February 13, 2024 07:33
@joshuay03 joshuay03 force-pushed the raise-on-invalid-distinct-args branch from 9da87fb to 84dee04 Compare February 13, 2024 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Relation #distinct doesn't raise an error for invalid arguments
4 participants