2011-09-01 7 views
7

私は、ドキュメントからこの例外を発生させる代わりに、before_add関連のコールバックで静かにスキップしますか?

has_many :roles, :before_add => :enforce_unique 

def enforce_unique(assoc) 
    false if exists? assoc 
end 

をやろうとしている:「before_addコールバックが例外をスローした場合、オブジェクトはコレクションに追加されません」。アドオンを防ぐことはできません偽以上使用して、私はこれを行うことを余儀なくしています:

def enforce_unique(assoc) 
    raise if exists? assoc 
end 

この方法では、それは追加されませんというのは本当だが、それも取り扱われなければなら例外を発生させます。あまり役に立ちません。私は通常のARコールバックbefore_saveのように振る舞い、FALSEを返すことでも保存(または追加)はできませんが、例外は発生しません。

上記のケースでは、私は無意識にassocを追加しないことをお勧めします。これを行う方法はありますか?私は何かを欠いている?あるいは例外をここで唯一のオプションとしていますか?

答えて

1

協会が多型ではない場合、あなたのような何かを行うことができます:あなたはこの質問は少し古いです

1

に関連付けされているものを私達にname_of_model役割の内側

validates_uniqueness_of :name_of_model 

を、しかし、私は出会いました最近同じ問題が発生しています。ここで私はそれを解決する方法である:

def enforce_unique |obj, x| 
    v = obj.roles 
    if i = v.index(x) 
    v.slice! i 
    end 
end 
2

私が思うにそれを解決する方法は、Rubyでのフロー制御のためのものされ、throwcatchを使用することです。例外を発生させることは、例外的な状況ではないため、適切ではありません。

は私がやってしまった:

catch(:duplicate) do 
    association.create({}) 
end 

とし、その後before_addコールバックで、私がやった:

if(Class.where({}).first) 
    throw :duplicate 
end 

スローの詳細を/ここにキャッチ:

http://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue-im-so-confused/

0

ので、この質問は、それが含まれていることを防止するのではなく、節約に関するものです一時的に、リスト内のD(そのモデルの制御に興味を持っていないコントローラによって)あなたは、関連するモデルで保存上書きしようとすると、役割が存在する場合はそれを保存できませんでした:

class Role < ActiveRecord::Base 
    belongs_to :user, inverse_of: :roles 

    def save 
    super unless self.new_record? && user.has_existing_role?(self) 
    end 
end 

追記:私は「ドンビジネスロジックをどこかに置かなければならないので、Active Recordパターンと一緒に使用すると、スキニーコントローラの議論を買わないでください。 Active Recordのようなビジネスドメインのパターンが悪い場合(具体的にはRuby AR宝石を参照しない)、実際にはコントローラレイヤー上にレイヤーが存在する必要があります。これを実現する手段としてサービスオブジェクトやデコレータパターンを使用できます。

もう1つの方法は、関連付けのために<<のような更新メソッドをオーバーライドして、既存のものと一致する場合にそのロールを静かに削除することです。関連メソッドのオーバーライドに関する詳細は、ActiveRecord Association Class Methods Documentation

関連する問題