我正在尝试为has_many
标记的项目建模。项目可以有多个标签,但要求至少有3个预定义标签。
这是我到目前为止所拥有的:
class Item < ActiveRecord::Base
has_one :type, :through => :item_tags, :source => :tag
has_one :material, :through => :item_tags, :source => :tag
has_one :use, :through => :item_tags, :source => :tag
has_many :tag, :through => :item_tags
has_many :item_tags
end
当我尝试使用Item.find(1).type时,这给了我ActiveRecord::HasOneThroughCantAssociateThroughCollection
。
我不知道该怎么做。有人可以帮忙吗?
编辑:我也想通过item.type和item.use等找到三个预定义的标签。
答案 0 :(得分:1)
通过了解您希望如何设置数据库,首先考虑这一点会更容易。你想要:
表:标签
表:ItemTag
表:项目
所以,你的模型更像是:
class Item < ActiveRecord::Base
belongs_to :type, :class_name => 'Tag'
belongs_to :material, :class_name => 'Tag'
belongs_to :use, :class_name => 'Tag'
# Require these tags
validates_presence_of :type, :material, :use
has_many :item_tags
has_many :tags, :through => :item_tags
def list_tags
[type, material, use] + tags
end
end
因此,您的数据库将直接在项目表中包含三列,这些列链接到标记表。这些是通过验证所必需的,但您也可以在迁移中进行设置,以便在您希望的情况下使这些列不为空。其他可选标签保持相同的关系。
您想要belongs_to而不是has_one,因为这会将关系推送到您想要的项目。 Has_one将一个item_id列放在Tag表中,这不是您想要的。
要通过此方法使用其他标记显示三个必需的标记,我建议添加一个仅供此用途的函数,定义为上面的list_tags。
希望有所帮助!
答案 1 :(得分:0)
我认为您可能希望使用自定义验证来检查Item.tags是否包含您需要的那些,然后使用范围和类方法来使item.use,item.type等按您的意愿工作。< / p>
物品型号:
class Item < ActiveRecord::Base
has_many :tags, :class_name => 'ItemTag'
validate :has_type, :has_use, :has_material
# Access methods
def types
self.tags.types
end
def uses
self.tags.uses
end
def materials
self.tags.materials
end
private
# Custom validation methods
def has_type
unless tags.present? and tags.include?(ItemTag.types)
errors.add("Tags must include a type.")
end
end
def has_material
unless tags.present? and tags.include?(ItemTag.materials)
errors.add("Tags must include a material.")
end
end
def has_use
unless tags.present? and tags.include?(ItemTag.use)
errors.add("Tags must include a use.")
end
end
end
ItemTag模型:
class ItemTag < ActiveRecord::Base
scope :types, lambda { where(...) }
scope :materials, lambda { where(...) }
scope :uses, lambda { where(...) }
end
如果首选使用访问方法中的.first
,您可以抓住单次出现。您需要根据确定类型/材料/用途的方式来调整where(...)
查询。