これは私がやろうとしていることです。私はこれを共通の問題だと思っていましたが、どういうわけか関連トピックを見つけることができませんでした...Rails 3:ActiveRecordモデルのDBアダプタからの例外の処理
私はスコープの一意性制約を持つモデルを持っています。私はそうのように、移行のテーブルに一意のインデックスを定義することによって、これを行うことにしました:
class CreateLossRatios < ActiveRecord::Migration
def up
...
add_index :loss_ratios, [ :tool_id, :ends_at ], :unique => true
end
def down
...
end
end
このインデックスの一意性に違反するレコードを保存しようとしたときのActiveRecordが例外をスローします。今私はそれを検証エラーとして表示させたいと思います。私は、ActiveRecord :: RecordNotUniqueをLossRatioモデルで捕捉し、意味のあるメッセージでエラーハッシュを取り込むことが最善の方法だと考えました。私はそれのようにした:
class LossRatio < ActiveRecord::Base
belongs_to :tool
validates :rate, :ends_at, :tool, :presence => true
validates_numericality_of :rate
validates_inclusion_of :rate, :in => (0..1)
%w{ create save }.each do |name|
%W{ #{name} #{name}! }.each do |method|
define_method(method) do |*args|
begin
super(*args)
rescue ActiveRecord::RecordNotUnique => ex
self.errors.add(:ends_at, I18n.t('activerecord.errors.models.loss_ratio.attributes.ends_at.not_unique'))
end
end
end
end
end
これは動作しますが、少し厄介なようです。ここでは仮定していることを理解しています(つまり、別のDBレベルの一意性制約などを追加するとどうなりますか)。しかし、これを回避する方法はありません。このようなシナリオを扱う場合、より洗練されたソリューション/ベストプラクティスがありますか?
- 以来、私はこのロジックは、コントローラに属するとは思わない、私はrescue_fromを使用していると考えることができますが、私はしたいが、これを行わない 1つの選択肢は、私は、アプリケーションロジック にそれを透明にします
- ほとんどの場合、関連付けられたコントローラはありません(これらのオブジェクトは、別のモデルを介した関連付けとしてのみ作成されます)。
任意のインスタンスメソッドからスローされた例外からこのモデルレスキューを行う方法はありますか?私はクラスレベルのレスキュー句を使用しようとしましたが、何もキャッチしません。
もう1つの疑問は、ends_atにARスコープ検証を使用する必要があるかどうかです。 RecordNotUniqueが処理されても、オブジェクトは引き続き有効であるとみなされ、保存に失敗した後にタイムスタンプが設定されます。それは望ましくない副作用を引き起こすことができますか?あなたはまた、(gmaletteのような提案)モデルに一意性を確認する必要があり
validates_uniqueness_of :ends_at, :scope => :tool_id
以下の私のコメントの他に、 'save'は例外を発生させないでください。 trueまたはfalseを返します。 –
この場合、特に、ActiveRecordを迂回するDB制約によって検証が行われる場合、RecordNotUniqueは非bangメソッドによっても生成されます。 – HargrimmTheBleak