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

Support passing record to uniqueness validator's :conditions option #39602

Conversation

eliotsykes
Copy link
Contributor

Support passing record to uniqueness validator's :conditions option.

This allows building conditions based on the record's attributes.

E.g. To validate slug must be unique for the day of publication:

class Article < ApplicationRecord

  validates_uniqueness_of :slug,
    conditions: ->(record) {
      where(published_at: record.published_at.beginning_of_day..record.published_at.end_of_day)
    }

If this is a welcome addition, please say and I'll refine this and add test coverage.

@eliotsykes eliotsykes changed the title Support passing record to uniqueness validator's :conditions option Support passing record to uniqueness validator's :conditions option Jun 11, 2020
@p8
Copy link
Member

p8 commented Jun 12, 2020

Hi @eliotsykes.
To ensure uniqueness you probably also want a unique index in the database.
The Article example could also be solved by adding an extra column for the published_at date (without the time).

validates_uniqueness_of :slug, { scope: :published_at_date }

@eliotsykes
Copy link
Contributor Author

eliotsykes commented Jun 13, 2020

Thanks @p8, these techniques are in use but not entirely desirable for this particular project.

If this enhancement is a welcome addition, please say and I'll refine this and add test coverage.

@rails-bot
Copy link

rails-bot bot commented Sep 11, 2020

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.

@rails-bot rails-bot bot added the stale label Sep 11, 2020
@rails-bot rails-bot bot closed this Sep 18, 2020
@eugeneius
Copy link
Member

This seems like a useful feature, analogous to how association scopes can access the record.

The example in the description could be properly backed by an expression index.

@eugeneius eugeneius reopened this Sep 27, 2020
@rails-bot rails-bot bot removed the stale label Sep 27, 2020
@eliotsykes eliotsykes force-pushed the uniqueness-validator-pass-record-to-conditions branch from a29efcd to 443ec45 Compare October 4, 2020 12:30
Copy link
Member

@eugeneius eugeneius left a comment

Choose a reason for hiding this comment

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

Can you add a changelog entry and squash your commits?

conditions = options[:conditions]

relation = if conditions.arity.zero?
relation.merge(conditions)
Copy link
Member

Choose a reason for hiding this comment

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

Since options[:conditions] can only be a callable, I think we should skip the indirection via Relation#merge and call instance_exec here directly, so it's more obvious how this branch differs from the one below:

Suggested change
relation.merge(conditions)
relation.instance_exec(&conditions)

# validates_uniqueness_of :slug,
# conditions: ->(record) {
# where(published_at: record.published_at.beginning_of_day..record.published_at.end_of_day)
# }
Copy link
Member

Choose a reason for hiding this comment

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

This example should be incorporated into the API documentation instead, probably here.


today_midday = Time.current.midday

todays_topic = Topic.create!(title: "Highlights of the Day", written_on: today_midday)
Copy link
Member

Choose a reason for hiding this comment

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

RuboCop is complaining because this variable is assigned but unused.

If you want to keep it as documentation, you'll need to add a leading underscore:

Suggested change
todays_topic = Topic.create!(title: "Highlights of the Day", written_on: today_midday)
_todays_topic = Topic.create!(title: "Highlights of the Day", written_on: today_midday)

@eliotsykes eliotsykes force-pushed the uniqueness-validator-pass-record-to-conditions branch from 31f1a7f to ab20be8 Compare October 5, 2020 13:19
@eliotsykes
Copy link
Contributor Author

Thanks for the feedback @eugeneius, I think this is ready now.

@eugeneius eugeneius merged commit 04dcf56 into rails:master Oct 5, 2020
@eugeneius
Copy link
Member

Thank you @eliotsykes! 🙌

@hpjaj
Copy link

hpjaj commented Oct 11, 2020

Nice work @eliotsykes ! 👏 👏

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.

4 participants