我对红宝石和红宝石路轨很陌生。我需要实现复杂的标记引擎:
programming
、ruby
和c
。然后,programming
是ruby
和c
的超级标记,当我输入关于ruby的标签时,没有必要输入标记programming
,我只能用ruby
标记它。当我输入标记时,应该递归地添加所有的超级标记。(事实上,奇怪的是,我从未见过任何带有此功能的标签引擎,我真的感到缺少它)Tag
belongs_to
User
。标签对任何人来说都不是公开的,它的所有者是私密的。看来我不能使用acts_as_taggable_on
宝石了,对吧?所以我必须实现我自己的梦想。实际上,我已经实现了支持层次结构、同义词和用户之类的Tag
类,它似乎很有效。但是,有很多问题,如何用它来使一些东西变得容易扭曲。
我正试图逆向设计acts_as_taggable_on
,这对像我这样的新手来说真的很复杂。
所以,有很多问题,但我现在要说的更具体一些:
假设我有一个类Item
,我想要成为taggable。据我所知,我应该在Item
和Tag
端使用Item
关联。因此,使用item_id
和tag_id
字段创建中间表。
但是:我希望我的标签引擎是通用的!因此,我不想在Tag
模型中添加任何与Item
相关的内容。
因此,唯一真正的问题是:通常只在Item
端创建has_many :through
关联可以吗?
其次,如果有人对我解释的东西有什么建议的话,我会很高兴看到他们的。
发布于 2013-12-25 11:41:13
至于swapnilabnave的好答案,我会解释你要找的是什么:
我建议把你的问题分解成更多的模块化问题。
您的问题是,您是否可以将has_many :through
用于关系。正如所解释的,答案是“是”,但这并不能完全解决问题。
标签层次结构
如前所述,您的标签将有“父母”和其他项目。
虽然我在Rails和CakePHP方面没有丰富的经验,但这将被称为树结构。CakePHP通过3列( parent_id
、left
、right
)来处理这个问题。这些基本允许应用程序具体显示树中的各种项,根据这些项在这3列中使用数字。
在您的例子中,我建议在parent_id
数据库中放置一个tags
列,如果需要的话,您可以为它分配一个超级标记(似乎每个标记只有一个超级标记?)。您可以在您的模型中使用自指协会技术来处理这一问题,该技术发布了swapnilabnave,可以这样调用super_tag
:
@tag.super_tag
重要的是,只有在每个标记只能有一个super_tag
时,这才能起作用。如果您希望每个标签有无限数量的超级标签,您可以这样做:
class Tag < ActiveRecord::Base
has_many :sub_tags, class_name: "Tag", :foreign_key => "super_tag_id"
has_many :tag_super_tags, class_name: "TagSuperTag", :foreign_key => "super_tag_id"
has_many :super_tags, :through => :tag_super_tags
end
Class TagSuperTag
belongs_to :tag
belongs_to :super_tag, :class => "Tag"
end
虽然我不确定join模型代码是否有效,但希望它能在这里向您展示这个想法。这将创建一个名为TagSuperTag的自引用连接模型,并允许您拥有如下表:
tag_super_tags
id | tag_id | super_tag_id | created_at | updated_at
tags (no need for super_tag_id)
id | user_id | name | etc
这将允许您在每个标记中添加任意数量的超级标记。
用户有许多标记
因为每个用户都有许多标记,所以您只需使用标准的has_many
关联,如下所示:
class User < ActiveRecord::Base
has_many :tags
end
class Tag < ActiveRecord::Base
belongs_to :user
end
这意味着每个标记必须有一个user_id
列,才能充当foreign_key
。
标签是通用的
要使标记通用(不仅仅是对于item
)需要一个polymorphic association
,而且似乎是一个连接模型。
正如swapnilabnave所描述的,任何想要使用它存储标记的模型都可以访问这个连接模型,从而允许您将任何模型与其关联起来。以下是你如何做到的:
class TaggedItem < ActiveRecord::Base
belongs_to :taggable, polymorphic: true
belongs_to :tag
end
tagged_items
id | taggable_type | taggable_id | tag_id | created_at | updated_at
这将允许您引用任何其他模型,如下所示:
class Post < ActiveRecord::Base
has_many :tagged_items, :class_name => "TaggedItem", :as => :taggable, :dependent => :destroy
has_many :tags, :through => :tagged_items
end
class Email < ActiveRecord::Base
has_many :tagged_items, :class_name => "TaggedItem", :as => :taggable, :dependent => :destroy
has_many :tags, :through => :tagged_items
end
Tag
模型也应该has_many :tagged_items
:
class Tag < ActiveRecord::Base
has_many :tagged_items, :class_name => "TaggedItem", :foreign_key => "tag_id", :dependent => :destroy
end
希望这能有所帮助
发布于 2013-12-24 22:27:21
我可以给你一些建议,一些事情可以帮助你的一些/大部分的问题陈述。
应该有一个标签的层次结构,
自引用has_many关联可以使用创建具有树结构的模型
class Tag < ActiveRecord::Base
has_many :sub_tags, class_name: "Tag", :foreign_key => "super_tag_id"
belongs_to :super_tag, class_name: "Tag"
end
,我想我的标签引擎是通用的!所以我不想在标签模型中添加任何与项目相关的内容
标记应该是多态的,因为它广泛适用于使用。
class TaggedItem < ActiveRecord::Base
belongs_to :tag
belongs_to :taggable, polymorphic: true
end
一般只在项目端创建has_many :通过关联吗?
我想是的,has_may through
是该走的路。所以您的Item
模型可能看起来像
class Item < ActiveRecord::Base
has_many :tags, as: :taggable, through: :tagged_items
end
https://stackoverflow.com/questions/20766464
复制相似问题