サラのソリューションを実装しようとすると、2 つの問題が発生しました。
まず、次のようにして同義語を割り当てたい場合、ソリューションは機能しません
word.synonyms << s1 or word.synonyms = [s1,s2]
また、シノニムを間接的に削除すると、正しく機能しません。これは、Rails が Link レコードを自動的に作成または削除するときに、 after_save_on_create および after_destroy コールバックをトリガーしないためです。少なくとも、私が試したRails 2.3.5ではそうではありませんでした。
これは、Word モデルで :after_add および :after_remove コールバックを使用することで修正できます。
has_many :synonyms, :through => :links,
:after_add => :after_add_synonym,
:after_remove => :after_remove_synonym
コールバックはサラのメソッドで、わずかに調整されています。
def after_add_synonym synonym
if find_synonym_complement(synonym).nil?
Link.new(:word => synonym, :synonym => self).save
end
end
def after_remove_synonym synonym
if complement = find_synonym_complement(synonym)
complement.destroy
end
end
protected
def find_synonym_complement synonym
Link.find(:first, :conditions => ["word_id = ? and synonym_id = ?", synonym.id, self.id])
end
Sarah の解決策の 2 番目の問題は、新しい単語と一緒にリンクされたときに他の単語が既に持っている同義語が新しい単語に追加されず、その逆も同様であるということです。この問題を修正し、グループのすべてのシノニムが常にそのグループ内の他のすべてのシノニムにリンクされるようにする小さな変更を次に示します。
def after_add_synonym synonym
for other_synonym in self.synonyms
synonym.synonyms << other_synonym if other_synonym != synonym and !synonym.synonyms.include?(other_synonym)
end
if find_synonym_complement(synonym).nil?
Link.new(:word => synonym, :synonym => self).save
end
end