has_many :通过 Rails 中的 has_and_belongs_to_many

发布于 2025-01-08 17:37:46 字数 911 浏览 0 评论 0原文

在 Rails 中 - 使用 has_many :through 和 has_and_belongs_to_many 的效果是什么? 考虑有两个模型 - 帖子和标签,它们具有多对多关系,如下所示:

class Tag < ActiveRecord::Base
  has_many :posts_tag
  has_and_belongs_to_many :posts
end

class Post < ActiveRecord::Base
  has_many :posts_tag
  has_many :tags,  :through => posts_tag
end

class PostsTag < ActiveRecord::Base
  belongs_to :tag
  belongs_to :post
end

我使用 has_and_belongs_to_many 的原因是因为 tag 属于许多帖子。

我确实查看了 Rails Association 指南,发现他们很多时候都没有提到这种情况一对多关系。然而,我确实尝试了这个,并且在 Rails 中运行它没有产生任何行为,并且从我构建的小型测试数据库来看,似乎也返回了 post.tags的正确结果tag.posts - 其中 posttag 引用 PostTag 模型的实例分别。

这是正确的用法还是有任何我不知道的副作用?另外,如果它是正确的,这是实现这一目标的 Rails 方法吗?

谢谢!

In Rails - what is the effect of using has_many :through with has_and_belongs_to_many?
Consider having two models - Posts and Tags which have a many-to-many relationship as indicated below:

class Tag < ActiveRecord::Base
  has_many :posts_tag
  has_and_belongs_to_many :posts
end

class Post < ActiveRecord::Base
  has_many :posts_tag
  has_many :tags,  :through => posts_tag
end

class PostsTag < ActiveRecord::Base
  belongs_to :tag
  belongs_to :post
end

The reason I use has_and_belongs_to_many is because a tag belongs to many posts.

I did look into the Rails Association guide and see that they don't mention this case for a many-to-many relationship. I, however, did try this and running it in Rails didn't yield any behavior and from the small test database that I built, also seemed to return the correct results for post.tags and tag.posts - where post and tag refer to an instance of the Post and Tag models respectively.

Is this correct usage or does it have any side affects that I am not aware of? Also, if it is correct, is this the Rails way of achieving this?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

恍梦境° 2025-01-15 17:37:46

仅当您设置多对多关联时(换句话说,当另一方也有 has_and_belongs_to_many 时),才使用 has_and_belongs_to_many。这就是这个协会的意义。

您应该

class Tag < ActiveRecord::Base
  has_many :posts_tags
  has_many :posts, :through => :post_tags
end

class PostsTag < ActiveRecord::Base
  belongs_to :tag
  belongs_to :post
end

class Post < ActiveRecord::Base
  has_many :posts_tags
  has_many :tags, :through => :posts_tags
end

注意到我使用了复数 post_tags (因为这是正确的方式)。

如果您遇到评论中的情况,则您

belongs_to :post_tag

Post 模型和

has_many :posts

PostTag 模型中应该有一个。

您现在可能会问:“为什么我应该使用 belongs_to :post_tag?它不属于标签,它一个标签。所以,我不应该使用 has_one :post_tag 吗?”。起初这也是我的问题,但后来我发现 Rails 并不总是完全适合英语。您需要 post 上的 post_tag_id 列,而 belongs_to 正是如此。另一方面,has_one 会期望名为 post_id 的列出现在另一端,即您的 post_tag< /代码>。但这是不可能的,因为 post_tag 有很多 post(不仅仅是一个),因此 post ID 不能保存在 post_tags 中

更新
关联之间的区别仅在于提供的方法和可以传入的选项(Rails 关联指南中解释的选项)。例如,has_onebelongs_to 具有相同的方法:

association(force_reload = false)
association=(associate)
build_association(attributes = {})
create_association(attributes = {})

但是,例如,方法 association=create_association 意味着关于外键应该在哪里的不同事情(就像我上面解释的那样)。

has_and_belongs_to_manyhas_many 的方法可能没有任何不同,但它们在您可以传递的选项方面有所不同。例如,您可以传入

:dependent => :destroy

has_many 关联,但不能将其传递给 has_and_belongs_to_many,因为这没有意义,因为它意味着许多- 多对多关联;如果父记录被销毁,子记录仍然可以与其他记录连接,因此它们不应该也被销毁。

You use has_and_belongs_to_many only when you're setting a many-to-many association (in other words, when the other side also has has_and_belongs_to_many). That is the meaning of this association.

You should have

class Tag < ActiveRecord::Base
  has_many :posts_tags
  has_many :posts, :through => :post_tags
end

class PostsTag < ActiveRecord::Base
  belongs_to :tag
  belongs_to :post
end

class Post < ActiveRecord::Base
  has_many :posts_tags
  has_many :tags, :through => :posts_tags
end

Notice that I used the plural, post_tags (because this is the correct way).

If you have the situation like in your comment, you should have a

belongs_to :post_tag

in your Post model, and

has_many :posts

in your PostTag model.

You may ask now: "Why should I use belongs_to :post_tag? It doesn't belong to a tag, it has a tag. So, shouldn't I use has_one :post_tag?". This was also my question at first, but then I figured that it Rails cannot always perfectly suit the english language. You need the post_tag_id column on your post, and belongs_to expects exactly that. On the other hand, has_one would expect that a column named post_id is present on the other side, that is in your post_tag. But this would be impossible, because post_tag has many posts (not only one), so the post IDs cannot be held in post_tags.

Update:
The difference between associations are only in the methods you are provided and options you can pass in (the one explained in the Rails guide on associations). For example, has_one and belongs_to have the same methods:

association(force_reload = false)
association=(associate)
build_association(attributes = {})
create_association(attributes = {})

But, for example, methods association= and create_association imply different things concerning where the foreign key should be (like I explained above).

has_and_belongs_to_many and has_many probably don't have anything different in their methods, but they differ in the options you can pass. For example, you can pass in

:dependent => :destroy

on the has_many association, but you can't pass it to a has_and_belongs_to_many, because that wouldn't make sense, since it implies a many-to-many association; if a parent record is destroyed, child records can still be connected with other records, so they shouldn't also be destroyed.

花开雨落又逢春i 2025-01-15 17:37:46

虽然我不确定在关系的一侧使用 has_many :through 和在另一侧使用 has_and_belongs_to_many 的确切效果,但我确实知道正确的方法是使用反向的 has_many :through ,如下所示:

class Tag < ActiveRecord::Base
  has_many :posts_tag
  has_many :posts,  :through => posts_tag
end

保持其他关系相同。

While I'm not sure of the exact effects of having a has_many :through on one side of a relationship and a has_and_belongs_to_many on the other side, I do know that the more correct way, would be to use a reversed has_many :through like so:

class Tag < ActiveRecord::Base
  has_many :posts_tag
  has_many :posts,  :through => posts_tag
end

Keeping the other relationships the same.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文