acts_as_paranoid + ユニークインデックス
Railsで論理削除を行うときはacts_as_paranoidを使用するのが一般的です。
Model側でvalidates_uniqueness_of_without_deletedを使用するとユニーク制限をかけることができますが、DB側でユニーク制限をかけようとすると問題が発生します。
# schema.rb create_table "customers", :force => true do |t| t.string "code", :null => false t.datetime "deleted_at" t.datetime "created_at" t.datetime "updated_at" end add_index "customers", ["code", "deleted_at"], :name => "customers_idx01", :unique => true
一見正しそうですがnullはユニーク制限の対象外となり次のようなレコードが入ってしまいます。
|code|deleted_at| |001| NULL| |001| NULL|
こういう時はindexにwhere条件を指定して直接DBに設定しましょう。
class AddIndexCodeToCustomers < ActiveRecord::Migration def self.up sql = 'create unique index customers_idx01 on customers (code) where deleted_at is null;' ActiveRecord::Base.connection.execute(sql) end def self.down remove_index :customers, :name => :customers_idx01 end end
procedureを使用してDBの操作を行うとRailsのModelを経由しないのでバリデーションが行われません。そういった場合はDB側でもチェックを行いたいですね。