STI 和多晶型物

发布于 2024-08-28 13:10:24 字数 701 浏览 14 评论 0原文

我的代码有问题

class Post < ActiveRecord::Base
end

class NewsArticle < Post
  has_many :comments, :as => :commentable, :dependent => :destroy, :order => 'created_at'
end

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true, :counter_cache => true
end

,在尝试获取一些新闻文章的评论时,我在日志中看到类似

  Comment Load (0.9ms)   SELECT "comments".* FROM "comments" WHERE ("comments"."commentable_id" = 1 and "comments"."commentable_type" = 'Post') ORDER BY created_at

奇怪的“commentable_type”='Post'。 怎么了?

PS:Rails 2.3.5 && ruby 1.8.7 (2010-01-10 补丁级别 249) [i686-darwin10]

I have problem with my code

class Post < ActiveRecord::Base
end

class NewsArticle < Post
  has_many :comments, :as => :commentable, :dependent => :destroy, :order => 'created_at'
end

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true, :counter_cache => true
end

And on attempt go get comments for some NewsArticle i see in logs something like

  Comment Load (0.9ms)   SELECT "comments".* FROM "comments" WHERE ("comments"."commentable_id" = 1 and "comments"."commentable_type" = 'Post') ORDER BY created_at

Strange that "commentable_type" = 'Post'.
What's wrong?

PS: Rails 2.3.5 && ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-darwin10]

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

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

发布评论

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

评论(5

梦回梦里 2024-09-04 13:10:24

commentable_type 字段需要存储包含数据的表的名称,一旦从右表加载该行,继承的类型将从 type 列加载在帖子表上。

所以:

这里的注释指向它所注释的表。 posts 表,id 1

>> Comment.first
=> #<Comment id: 1, commentable_id: 1, commentable_type: "Post", body: "test", created_at: "2010-04-09 00:56:36", updated_at: "2010-04-09 00:56:36">

然后加载 NewsArticle,id 1 是从 posts 中加载的,那里的类型表示 NewsArticle。

>> Comment.first.commentable
=> #<NewsArticle id: 1, type: "NewsArticle", name: "one", body: "body", created_at: "2010-04-09 00:55:35", updated_at: "2010-04-09 00:55:35">
>> Comment.first.commentable.class.table_name
=> "posts"

如果commentable_type持有“NewsArticle”,则必须查看该类来确定表格。这样它就可以只查看表并在到达那里后担心类型。

The commentable_type field needs to store the name of the table that contains the data, once that row is loaded from the right table, the inherited type will be loaded from the type column on the Posts table.

So:

Here the comment points to the table that it comments on. The posts table, id 1

>> Comment.first
=> #<Comment id: 1, commentable_id: 1, commentable_type: "Post", body: "test", created_at: "2010-04-09 00:56:36", updated_at: "2010-04-09 00:56:36">

Then to load the NewsArticle, id 1 is loaded from posts, and the type there indicates a NewsArticle.

>> Comment.first.commentable
=> #<NewsArticle id: 1, type: "NewsArticle", name: "one", body: "body", created_at: "2010-04-09 00:55:35", updated_at: "2010-04-09 00:55:35">
>> Comment.first.commentable.class.table_name
=> "posts"

If commentable_type held "NewsArticle" it would have to look at the class to determine the table. This way it can just look to the table and worry about the type once it gets there.

稍尽春風 2024-09-04 13:10:24

查看 ActiveRecord::Associations API 的多态关联部分。有一些关于将多态关联与单表继承结合使用的内容。按照该部分中的第二个代码示例,我认为这可能接近您想要的

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true, :counter_cache => true

  def commentable_type=(sType)
   super(sType.to_s.classify.constantize.base_class.to_s)
  end
end

class Post < ActiveRecord::Base
  has_many :comments, :as => :commentable, :dependent => :destroy, :order => 'created_at'
end

class NewsArticle < Post
end

Take a look at the Polymorphic Associations section of ActiveRecord::Associations API. There is a little bit about using polymorphic associations in combination with single table inheritance. Following the second code example in that section I think this might be close to what you want

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true, :counter_cache => true

  def commentable_type=(sType)
   super(sType.to_s.classify.constantize.base_class.to_s)
  end
end

class Post < ActiveRecord::Base
  has_many :comments, :as => :commentable, :dependent => :destroy, :order => 'created_at'
end

class NewsArticle < Post
end
夜空下最亮的亮点 2024-09-04 13:10:24

def commentable_type=(sType)
超级(sType.to_s.classify.constantize.base_class.to_s)
该方法返回

的类为Post,如果想将继承的类Post存储为commentable_type怎么办?

def commentable_type=(sType)
super(sType.to_s.classify.constantize.base_class.to_s)
end

This method is returning class as Post, what to do if you want to store the inherited class Post as commentable_type?

手心的海 2024-09-04 13:10:24

好问题。我在使用 Rails 3.1 时遇到了完全相同的问题。看来问题还没有解决。显然,在 Rails 中将多态关联与单表继承 (STI) 结合使用有点复杂。

Rails 3.2 的当前 Rails 文档给出了组合 多态的建议协会和性传播感染

结合单表使用多态关联
继承(STI)有点棘手。为了让各协会
按预期工作,确保存储 STI 的基本模型
多态关联的类型列中的模型。

在您的情况下,基本模型将是“Post”,即所有评论的“commentable_type”应该是“Post”。

Good question. I had exactly the same problem using Rails 3.1. Looks the problem is not solved yet. Apparently, using polymorphic associations in combination with Single Table Inheritance (STI) in Rails is a bit complicated.

The current Rails documentation for Rails 3.2 gives this advice for combining polymorphic associations and STI:

Using polymorphic associations in combination with single table
inheritance (STI) is a little tricky. In order for the associations to
work as expected, ensure that you store the base model for the STI
models in the type column of the polymorphic association.

In your case the base model would be "Post", i.e. "commentable_type" should be "Post" for all comments.

弥枳 2024-09-04 13:10:24

从技术上来说,这实际上并没有什么问题。当 Rails 处理多态关联,并且关联的对象使用 STI 时,它只是使用基类作为类型(在您的例子中为“commentable_type”)。

如果您将 Post 和 NewsArticle 放在单独的表中,显然 commentable_type 将分别显示为 Post 和 NewsArticle。

Technically, there's actually nothing wrong with this. When Rails is dealing with a polymorphic association, and the object being associated is using STI, it simply uses the base class as the type (in your case "commentable_type").

If you have Post and NewsArticle in separate tables, obviously the commentable_type will show up as Post and NewsArticle respectively.

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