首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Rails: has_many :只在一侧通过关联

Rails: has_many :只在一侧通过关联
EN

Stack Overflow用户
提问于 2013-12-24 20:32:38
回答 2查看 1.3K关注 0票数 0

我对红宝石和红宝石路轨很陌生。我需要实现复杂的标记引擎:

  • 每个标签可以有0或更多的同义词(是的,就像这样)
  • 应该有一个标签的层次结构:即有子标签和超级标签。比如说,我有三个标签:programmingrubyc。然后,programmingrubyc的超级标记,当我输入关于ruby的标签时,没有必要输入标记programming,我只能用ruby标记它。当我输入标记时,应该递归地添加所有的超级标记。(事实上,奇怪的是,我从未见过任何带有此功能的标签引擎,我真的感到缺少它)
  • 每个用户都应该有自己的标记集,即每个Tag belongs_to User。标签对任何人来说都不是公开的,它的所有者是私密的。

看来我不能使用acts_as_taggable_on宝石了,对吧?所以我必须实现我自己的梦想。实际上,我已经实现了支持层次结构、同义词和用户之类的Tag类,它似乎很有效。但是,有很多问题,如何用它来使一些东西变得容易扭曲。

我正试图逆向设计acts_as_taggable_on,这对像我这样的新手来说真的很复杂。

所以,有很多问题,但我现在要说的更具体一些:

假设我有一个类Item,我想要成为taggable。据我所知,我应该在ItemTag端使用Item关联。因此,使用item_idtag_id字段创建中间表。

但是:我希望我的标签引擎是通用的!因此,我不想在Tag模型中添加任何与Item相关的内容。

因此,唯一真正的问题是:通常只在Item端创建has_many :through关联可以吗?

其次,如果有人对我解释的东西有什么建议的话,我会很高兴看到他们的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-25 11:41:13

至于swapnilabnave的好答案,我会解释你要找的是什么:

我建议把你的问题分解成更多的模块化问题。

您的问题是,您是否可以将has_many :through用于关系。正如所解释的,答案是“是”,但这并不能完全解决问题。

标签层次结构

如前所述,您的标签将有“父母”和其他项目。

虽然我在Rails和CakePHP方面没有丰富的经验,但这将被称为树结构。CakePHP通过3列( parent_idleftright )来处理这个问题。这些基本允许应用程序具体显示树中的各种项,根据这些项在这3列中使用数字。

在您的例子中,我建议在parent_id数据库中放置一个tags列,如果需要的话,您可以为它分配一个超级标记(似乎每个标记只有一个超级标记?)。您可以在您的模型中使用自指协会技术来处理这一问题,该技术发布了swapnilabnave,可以这样调用super_tag

代码语言:javascript
运行
复制
@tag.super_tag 

重要的是,只有在每个标记只能有一个super_tag时,这才能起作用。如果您希望每个标签有无限数量的超级标签,您可以这样做:

代码语言:javascript
运行
复制
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的自引用连接模型,并允许您拥有如下表:

代码语言:javascript
运行
复制
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关联,如下所示:

代码语言:javascript
运行
复制
class User < ActiveRecord::Base
  has_many :tags
end

class Tag < ActiveRecord::Base
 belongs_to :user
end

这意味着每个标记必须有一个user_id列,才能充当foreign_key

标签是通用的

要使标记通用(不仅仅是对于item)需要一个polymorphic association,而且似乎是一个连接模型。

正如swapnilabnave所描述的,任何想要使用它存储标记的模型都可以访问这个连接模型,从而允许您将任何模型与其关联起来。以下是你如何做到的:

代码语言:javascript
运行
复制
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

这将允许您引用任何其他模型,如下所示:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
class Tag < ActiveRecord::Base
    has_many :tagged_items, :class_name => "TaggedItem", :foreign_key => "tag_id", :dependent => :destroy
end

希望这能有所帮助

票数 1
EN

Stack Overflow用户

发布于 2013-12-24 22:27:21

我可以给你一些建议,一些事情可以帮助你的一些/大部分的问题陈述。

应该有一个标签的层次结构,

自引用has_many关联可以使用创建具有树结构的模型

代码语言:javascript
运行
复制
class Tag < ActiveRecord::Base
  has_many :sub_tags, class_name: "Tag", :foreign_key => "super_tag_id"
  belongs_to :super_tag, class_name: "Tag"
end

,我想我的标签引擎是通用的!所以我不想在标签模型中添加任何与项目相关的内容

标记应该是多态的,因为它广泛适用于使用。

代码语言:javascript
运行
复制
class TaggedItem < ActiveRecord::Base
  belongs_to :tag
  belongs_to :taggable, polymorphic: true
end

一般只在项目端创建has_many :通过关联吗?

我想是的,has_may through是该走的路。所以您的Item模型可能看起来像

代码语言:javascript
运行
复制
class Item < ActiveRecord::Base
  has_many :tags, as: :taggable, through: :tagged_items
end
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20766464

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档