Skip to content

Instantly share code, notes, and snippets.

@cmbankester
Last active January 8, 2016 19:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cmbankester/a6dd52ecb1255094a1f1 to your computer and use it in GitHub Desktop.
Save cmbankester/a6dd52ecb1255094a1f1 to your computer and use it in GitHub Desktop.
Rails Validator for Uniqueness Among Records Unmarked for Destruction
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
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment