我目前有这些型号:
class Base < ActiveRecord::Base
has_many :base_tags
has_many :tags, through: :base_tags
has_many :primary_tags, through: :base_tags, class_name: 'Tag', source: :tag, conditions: ['base_tags.primary = ?', true]
has_and_belongs_to_many :channels
end
class Tag < ActiveRecord::Base
has_many :base_tags
has_many :bases, through: :base_tags
end
class BaseTag < ActiveRecord::Base
belongs_to :base
belongs_to :tag
end
我正在努力在基础模型上实现主要标签。在基础实例上调用#primary_tags会返回正确的记录,但在尝试创建/更新记录时:
Base.create({tag_ids: [1,2], primary_tag_ids: [1]})
我遇到了以下错误:
ActiveRecord::RecordNotUnique
Mysql2::Error: Duplicate entry '1-2' for key 'index_bases_tags_on_base_id_and_tag_id': INSERT INTO `base_tags` (`base_id`, `primary`, `tag_id`) VALUES (1, 0, 2)
ActiveRecord尝试为primary_tag_ids创建与tag_ids相同的关联,当它应该真正更新关系时,主要属性应为1。
有没有办法让ActiveRecord玩得好听?我想我的has_many:primary_tags关系不正确。
答案 0 :(得分:2)
我认为有两个问题。
首先,如果你使用字符串形式的条件,那么activerecord就无法解析那个sql片段并理解它应该设置什么属性。
其次,因为这是一个有很多通过,我认为这些条件需要在连接模型关联
使用这样的模型
class Base < ActiveRecord::Base
has_many :base_tags
has_many :primary_base_tags, conditions: {primary: true}, class_name: 'BaseTag'
has_many :tags, through: :base_tags
has_many :primary_tags, through: :primary_base_tags, class_name: 'Tag', source: :tag
end
然后activerecord为我正确设置主标志。
答案 1 :(得分:0)
此解决方案可能适合您。我还添加了访问primary_tags
的替代版本,但由于您的版本有效,您可能不需要它。
class Base < ActiveRecord::Base
has_many :base_tags
has_many :tags, through: :base_tags
has_and_belongs_to_many :channels
def primary_tags
self.tags.includes(:base_tags).where(base_tags: { primary: true } )
end
def primary_tags_ids=(ids)
current_ids = self.base_tags.map(&:tag_id)
ids.each do |id|
if current_ids.include?(id)
self.base_tags.select { |bt| bt.tag_id == id }.first.primary = true
else
self.base_tags.build( { tag_id: id, primary: true } )
end
end
end
end