1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Support passing record to uniqueness conditions

This commit is contained in:
Eliot Sykes 2020-06-11 16:04:30 +01:00
parent ae5ecfe26c
commit ab20be81e3
No known key found for this signature in database
GPG key ID: 5D4BD2923931D657
3 changed files with 51 additions and 1 deletions

View file

@ -1,3 +1,16 @@
* Support passing record to uniqueness validator `:conditions` callable:
```ruby
class Article < ApplicationRecord
validates_uniqueness_of :title, conditions: ->(article) {
published_at = article.published_at
where(published_at: published_at.beginning_of_year..published_at.end_of_year)
}
end
```
*Eliot Sykes*
* `BatchEnumerator#update_all` and `BatchEnumerator#delete_all` now return the
total number of rows affected, just like their non-batched counterparts.

View file

@ -29,7 +29,16 @@ module ActiveRecord
end
end
relation = scope_relation(record, relation)
relation = relation.merge(options[:conditions]) if options[:conditions]
if options[:conditions]
conditions = options[:conditions]
relation = if conditions.arity.zero?
relation.instance_exec(&conditions)
else
relation.instance_exec(record, &conditions)
end
end
if relation.exists?
error_options = options.except(:case_sensitive, :scope, :conditions)
@ -126,6 +135,17 @@ module ActiveRecord
# validates_uniqueness_of :title, conditions: -> { where.not(status: 'archived') }
# end
#
# To build conditions based on the record's state, define the conditions
# callable with a parameter, which will be the record itself. This
# example validates the title is unique for the year of publication:
#
# class Article < ActiveRecord::Base
# validates_uniqueness_of :title, conditions: ->(article) {
# published_at = article.published_at
# where(published_at: published_at.beginning_of_year..published_at.end_of_year)
# }
# end
#
# When the record is created, a check is performed to make sure that no
# record exists in the database with the given value for the specified
# attribute (that maps to a column). When the record is updated,

View file

@ -522,6 +522,23 @@ class UniquenessValidationTest < ActiveRecord::TestCase
}
end
def test_validate_uniqueness_with_conditions_with_record_arg
Topic.validates_uniqueness_of :title, conditions: ->(record) {
where(written_on: record.written_on.beginning_of_day..record.written_on.end_of_day)
}
today_midday = Time.current.midday
todays_topic = Topic.new(title: "Highlights of the Day", written_on: today_midday)
assert todays_topic.save, "1st topic written today with this title should save"
todays_topic_duplicate = Topic.new(title: "Highlights of the Day", written_on: today_midday + 1.minute)
assert todays_topic_duplicate.invalid?, "2nd topic written today with this title should be invalid"
tomorrows_topic = Topic.new(title: "Highlights of the Day", written_on: today_midday + 1.day)
assert tomorrows_topic.valid?, "1st topic written tomorrow with this title should be valid"
end
def test_validate_uniqueness_on_existing_relation
event = Event.create
assert_predicate TopicWithUniqEvent.create(event: event), :valid?