2

アソシエーションを通じて多形has_manyのエントリの重複を防ぐ簡単な、または少なくともエレガントな方法はありますか?

タグ付けできるストーリーとリンクの2つのモデルがあります。ここではプラグインを使用しないという意識的な決断をしています。私は実際に起こっていることすべてを理解し、私が完全に理解していない他の誰かのコードに依存しないようにしたいです。

私の質問が何になっているのかを確認するために、コンソールで次のコマンドを実行した場合(ストーリーオブジェクトとタグオブジェクトがデータベースにすでに存在していると仮定)

s = Story.find_by_id(1)

t = Tag.find_by_id(1)

s.tags << t

s.tags << t

私のタギング結合テーブルには2つのエントリが追加され、それぞれに同じ正確なデータがあります(tag_id = 1、taggable_id = 1、taggable_type = "Story")。それは私にはあまり適切ではないようです。そこで、これを防ぐために、タグ付けモデルに次のものを追加しました。

before_validation :validate_uniqueness

def validate_uniqueness
    taggings = Tagging.find(:all, :conditions => { :tag_id => self.tag_id, :taggable_id => self.taggable_id, :taggable_type => self.taggable_type })

    if !taggings.empty?
        return false
    end

    return true
end

ほぼ意図したとおりに機能しますが、ストーリーまたはリンクに重複するタグを追加しようとすると、ActiveRecord :: RecordInvalid:Validationfailed例外が発生します。リストに関連付けを追加すると、保存と呼ばれるようです。(sansを保存するのではなく!)何かがうまくいかなかった場合に、単にfalseを返すのではなく、例外を発生させるメソッド。それは私がしたいことではありません。新しいタグを追加する試みはすべてtry/catchで囲むことができると思いますが、それは例外を予期してはならないという考えに反し、これは私が完全に期待していることです。

重複が存在するためにオブジェクトをデータベースにサイレントに保存しないだけの場合に例外を発生させない、これを行うためのより良い方法はありますか?

4

3 に答える 3

1

has_many関係を定義するときに、uniqオプションを設定できます。Rails APIドキュメントによると:

:uniq

trueの場合、重複はコレクションから除外されます。:throughと組み合わせて使用​​すると便利です。

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M001833の「Supportedoptions」小見出しから引用)

于 2010-05-22T12:15:15.143 に答える
1

あなたはそれをいくつかの方法で行うことができます。

既存のすべてのタグをロードしてから、新しいタグのみをチェックして追加するカスタムadd_tagsメソッドを定義します。

例:

def add_tags *new_tags
  new_tags = new_tags.first if tags[0].kind_of? Enumerable #deal with Array as first argument
  new_tags.delete_if do |new_tag|
    self.tags.any? {|tag| tag.name == new_tag.name}
  end
  self.tags += new_tags
end

また、before_saveフィルターを使用して、タグのリストに重複がないことを確認することもできます。これは、すべての保存で発生するため、少し多くのオーバーヘッドが発生します。

于 2010-05-22T17:43:29.550 に答える
0

私はこれがうまくいくと信じています...

class Tagging < ActiveRecord::Base
   validate :validate_uniqueness 

   def validate_uniqueness
      taggings = Tagging.find(:all, :conditions => {
         :tag_id => self.tag_id,
         :taggable_id => self.taggable_id,
         :taggable_type => self.taggable_type }) 

      errors.add_to_base("Your error message") unless taggings.empty? 
   end 
end

エラーなどが発生した場合はお知らせください:]

于 2010-05-22T14:59:49.023 に答える