diff --git a/lib/paranoia.rb b/lib/paranoia.rb index 3307267c..56425daf 100644 --- a/lib/paranoia.rb +++ b/lib/paranoia.rb @@ -172,4 +172,18 @@ def paranoia_column end end + require 'paranoia/rspec' if defined? RSpec + +module ActiveRecord + module Validations + class UniquenessValidator < ActiveModel::EachValidator + protected + def build_relation_with_paranoia(klass, table, attribute, value) + relation = build_relation_without_paranoia(klass, table, attribute, value) + relation.and(klass.quoted_table_name + ".#{klass.paranoia_column} IS NULL") + end + alias_method_chain :build_relation, :paranoia + end + end +end diff --git a/paranoia.gemspec b/paranoia.gemspec index b78d8377..8ec10e66 100644 --- a/paranoia.gemspec +++ b/paranoia.gemspec @@ -18,6 +18,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'bundler', '>= 1.0.0' s.add_development_dependency 'rake' + s.add_development_dependency 'test-unit' s.files = `git ls-files`.split("\n") s.executables = `git ls-files`.split("\n").map { |f| f =~ /^bin\/(.*)/ ? $1 : nil }.compact diff --git a/test/paranoia_test.rb b/test/paranoia_test.rb index 83457fa9..62b3a975 100644 --- a/test/paranoia_test.rb +++ b/test/paranoia_test.rb @@ -16,7 +16,7 @@ ActiveRecord::Base.connection.execute 'CREATE TABLE callback_models (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)' ActiveRecord::Base.connection.execute 'CREATE TABLE fail_callback_models (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)' ActiveRecord::Base.connection.execute 'CREATE TABLE related_models (id INTEGER NOT NULL PRIMARY KEY, parent_model_id INTEGER NOT NULL, deleted_at DATETIME)' -ActiveRecord::Base.connection.execute 'CREATE TABLE employers (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)' +ActiveRecord::Base.connection.execute 'CREATE TABLE employers (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME, name VARCHAR(10))' ActiveRecord::Base.connection.execute 'CREATE TABLE employees (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)' ActiveRecord::Base.connection.execute 'CREATE TABLE jobs (id INTEGER NOT NULL PRIMARY KEY, employer_id INTEGER NOT NULL, employee_id INTEGER NOT NULL, deleted_at DATETIME)' ActiveRecord::Base.connection.execute 'CREATE TABLE custom_column_models (id INTEGER NOT NULL PRIMARY KEY, destroyed_at DATETIME)' @@ -434,6 +434,13 @@ def test_observers_not_notified_if_not_supported a.restore! # essentially, we're just ensuring that this doesn't crash end + + def test_validates_uniqueness_only_checks_non_deleted_records + a = Employer.create!(name: "A") + a.destroy + b = Employer.new(name: "A") + assert b.valid? + end private def get_featureful_model @@ -498,6 +505,7 @@ class RelatedModel < ActiveRecord::Base class Employer < ActiveRecord::Base acts_as_paranoid + validates_uniqueness_of :name has_many :jobs has_many :employees, :through => :jobs end