has_and_belongs_to_many, избегая простофиль в объединяющей таблице

void function(void) {
  MY_TYPE a;
  a.flag = true;
  a.value = 15;
  a.stuff = 0.123;
}
57
задан Sam Saffron 15 July 2009 в 06:47
поделиться

4 ответа

I worked around this by creating a before_save filter that fixes stuff up.

class Post < ActiveRecord::Base 
   has_and_belongs_to_many :tags
   before_save :fix_tags

   def tag_list= (tag_list) 
      self.tags.clear 
      tag_list.strip.split(' ').each do 
        self.tags.build(:name => tag) 
      end
   end  

    def fix_tags
      if self.tags.loaded?
        new_tags = [] 
        self.tags.each do |tag|
          if existing = Tag.find_by_name(tag.name) 
            new_tags << existing
          else 
            new_tags << tag
          end   
        end

        self.tags = new_tags 
      end
    end

end

It could be slightly optimised to work in batches with the tags, also it may need some slightly better transactional support.

4
ответ дан 24 November 2019 в 19:25
поделиться

You can pass the :uniq option as described in the documentation. Also note that the :uniq options doesn't prevent the creation of duplicate relationships, it only ensures accessor/find methods will select them once.

If you want to prevent duplicates in the association table you should create an unique index and handle the exception. Also validates_uniqueness_of doesn't work as expected because you can fall into the case a second request is writing to the database between the time the first request checks for duplicates and writes into the database.

20
ответ дан 24 November 2019 в 19:25
поделиться

Я бы предпочел настроить модель и создать классы следующим образом:

class Tag < ActiveRecord::Base 
   has_many :taggings
   has_many :posts, :through => :taggings
end 

class Post < ActiveRecord::Base 
   has_many :taggings
   has_many :tags, :through => :taggings
end

class Tagging < ActiveRecord::Base 
   belongs_to :tag
   belongs_to :post
end

Затем я бы обернул создание в логику, чтобы модели тегов были повторно использованы, если они уже существовали. Я бы, вероятно, даже наложил уникальное ограничение на имя тега, чтобы обеспечить его соблюдение. Это делает поиск более эффективным в любом случае, поскольку вы можете просто использовать индексы в объединенной таблице (чтобы найти все сообщения для определенного тега и все теги для конкретного сообщения).

Единственная загвоздка в том, что вы можете ' • разрешить переименование тегов, поскольку изменение имени тега повлияет на все способы использования этого тега. Заставьте пользователя удалить тег и вместо этого создать новый.

5
ответ дан 24 November 2019 в 19:25
поделиться

Установите параметр uniq:

class Tag < ActiveRecord::Base 
   has_and_belongs_to_many :posts , :uniq => true
end 

class Post < ActiveRecord::Base 
   has_and_belongs_to_many :tags , :uniq => true
13
ответ дан 24 November 2019 в 19:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: