Trying to implement Sarah's solution, I ran into two problems:
Firstly, the solution does not work if you want to assign synonyms by doing
word.synonyms << s1 or word.synonyms = [s1,s2]
Also, removing indirect links does not work properly. This is because Rails does not start the after_save_on_create and after_destroy callbacks when it automatically creates or deletes Link entries. At least not in Rails 2.3.5, where I tried it.
This can be fixed using: after_add and: after_remove callbacks in the Word model:
has_many :synonyms, :through => :links, :after_add => :after_add_synonym, :after_remove => :after_remove_synonym
If the callbacks are Sarah's methods, slightly adjusted:
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
The second problem with Sarahโs solution is that synonyms that other words already have when connecting to a new word are not added to the new word and vice versa. Here is a small modification that fixes this problem and ensures that all synonyms of a group are always associated with all other synonyms in this group:
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
Nico
source share