class Foo < ActiveRecord::Base
belongs_to :bar, inverse_of: :foos
validates :some_attribute,
unmarked_for_destruction_uniqueness: {
parent: :bar
, children: :foos
# , message: "Some message"
}
end
Last active
January 8, 2016 19:17
-
-
Save cmbankester/a6dd52ecb1255094a1f1 to your computer and use it in GitHub Desktop.
Rails Validator for Uniqueness Among Records Unmarked for Destruction
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UnmarkedForDestructionUniquenessValidator < ActiveModel::EachValidator | |
# validates that record.<attribute> is unique among all non-marked-for- | |
# destruction 'siblings' of record, where 'siblings' are all objects | |
# record.<parent>.<children> such that the object is not the current record | |
# | |
# If an option such as 'ignore_records_marked_for_destruction: true' existed | |
# for the 'uniqueness' validator, this validator would do the same thing as: | |
# validates :attribute, | |
# uniqueness: { | |
# scope: :parent, | |
# ignore_records_marked_for_destruction: true | |
# } | |
def validate_each(record, attribute, value) | |
if options[:parent].nil? | |
fail ArgumentError, ":parent cannot be nil" | |
end | |
if options[:children].nil? | |
fail ArgumentError, ":children cannot be nil" | |
end | |
duped = record.send(options[:parent]).send(options[:children]).any? do |a| | |
a != record && !a.marked_for_destruction? && a.send(attribute) == value | |
end | |
if duped | |
record.errors[attribute] << ( | |
options[:message] || "has already been taken" | |
) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment