Goal
* RDBMS側で複合ユニークキーを設定している前提
* Railsのバリデーションによって、Insert SQLを投げる前に重複をチェックする
Preparation
$> uname -a
Linux *** 2.6.32-358.el6.i686 #1 SMP Thu Feb 21 21:50:49 UTC 2013 i686 i686 i386 GNU/Linux
$> cat /etc/issue
CentOS release 6.4 (Final)
Kernel \r on an \m
$> ruby -v
ruby 2.1.0p0 (2013-12-25 revision 44422) [i686-linux]
$> rails -v
Rails 4.0.2
Example
* ユーザが各課題に対して1日1つ日報を出すという設定.
* user(ユーザ)/date(日にち)/subject(課題)でユニークになるようにRDBMS設定している.
* validates_withヘルパでカスタムバリデータをよびだす
* カスタムバリデータはapp/validators以下に定義して、record変数で渡ってくるバリデーション対象でDB selectを実行する
app/model/daily_report.rb
class DailyReport < ActiveRecord::Base
belongs_to :user
validates_with DailyReportComplexUniqueValidator
end
app/validators/daily_report_complex_validator.rb
class DailyReportComplexUniqueValidator < ActiveModel::Validator
def validate(record)
daily_report = DailyReport.find_by(
user_id: record[:user_id],
date: record[:date],
subject: record[:subject]
)
if !daily_report.nil?
record.errors[:base] << 'user_id, date, subjectのデータがすでに存在しています。'
end
end
end