void function(void) {
MY_TYPE a;
a.flag = true;
a.value = 15;
a.stuff = 0.123;
}
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.
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.
Я бы предпочел настроить модель и создать классы следующим образом:
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
Затем я бы обернул создание в логику, чтобы модели тегов были повторно использованы, если они уже существовали. Я бы, вероятно, даже наложил уникальное ограничение на имя тега, чтобы обеспечить его соблюдение. Это делает поиск более эффективным в любом случае, поскольку вы можете просто использовать индексы в объединенной таблице (чтобы найти все сообщения для определенного тега и все теги для конкретного сообщения).
Единственная загвоздка в том, что вы можете ' • разрешить переименование тегов, поскольку изменение имени тега повлияет на все способы использования этого тега. Заставьте пользователя удалить тег и вместо этого создать новый.
Установите параметр 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