Rails:构建涉及多态关联和 STI 的查询

发布于 2024-11-19 01:06:53 字数 2103 浏览 1 评论 0原文

我正在尝试查找有关照片的 10 条最新评论,以便将它们集成到我的 Rails 3.0.3 应用程序上的活动提要中。

我有一个 Photo 模型,它使用单表继承从 Upload 模型继承:

class Upload < ActiveRecord::Base
    ...
end

class Photo < Upload
    has_many :comments, :as => :commentable
    ...
end

多态关联 commentablecommentable 中进行了描述。 >评论模型:

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

到目前为止还不错,对吧?当我尝试构建查询时,问题就出现了。经过一番试验和错误后,我想出了位于 Photo 模型中的这段代码:

def self.latest_comments(count = 10)
    Comment.where(:commentable_type => "Upload")\
       .joins("INNER JOIN uploads ON comments.commentable_id = uploads.id")\
       .where("uploads.type" => "Photo").order("comments.created_at DESC").limit(count)
end

这段代码可以在我的使用 SQLite 的开发机器上运行,但我必须进行一些更改才能使其在使用 PostgreSQL 的生产服务器上运行。上面的查询化身尚未在生产服务器上进行测试,但我一直在寻找一种更清晰的查询结构方式,因为上面的查询感觉不是很健壮,也不是很“Railsy”。

我想说的是

Comment.joins(:commentable => :photo)

......但这引发了一个例外,大概是因为 Rails 不知道如何进行连接:

ActiveRecord::EagerLoadPolymorphicError:无法急切加载多态关联:commentable

我在 StackOverflow 上发现了一篇 帖子 描述了查询多态关联的不同方式。我能够根据这篇文章想出以下代码:

Comment.find_all_by_commentable_type("Upload", :include => :commentable,
        :order => "created_at DESC", :limit => 10)

但是,这不适用于 STI:由于 Photo 继承自 Upload,我无法直接获取与照片相关的评论 - 只能获取所有类的评论继承自上传。

我看过很多与多态性或 STI 相关的其他帖子,但没有一个以我正在寻找的方式将两者结合起来。我可以简单地处理初始查询,但是有人对构建涉及多态性和 STI 的查询的替代方法有任何想法吗?

编辑:我在这里发现了另一个问题,与我的思路相同。不幸的是,最重要的答案没有提供我正在寻找的解决方案。如果我要将其应用于我的问题,我会将 has_many :comments 关联从 Photo 模型移动到 Upload 模型,并且向 Comment 类添加一些代码以确定 commentable 的正确类。这并不理想,因为它破坏了上传的任何子类都会有注释的建模。一定有更好的方法......?

I'm trying to find the 10 most recent comments on photos so I can integrate them into an activity feed on my Rails 3.0.3 application.

I've got a Photo model, which inherits from an Upload model using single table inheritance:

class Upload < ActiveRecord::Base
    ...
end

class Photo < Upload
    has_many :comments, :as => :commentable
    ...
end

The polymorphic association commentable is described in the Comment model:

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

So far so good, right? The problem comes when I try to construct a query. After some trial and error, I came up with this code that sits in the Photo model:

def self.latest_comments(count = 10)
    Comment.where(:commentable_type => "Upload")\
       .joins("INNER JOIN uploads ON comments.commentable_id = uploads.id")\
       .where("uploads.type" => "Photo").order("comments.created_at DESC").limit(count)
end

This code works on my development machine with SQLite, but I've had to make some changes to get it to work on the production server using PostgreSQL. The above incarnation of the query hasn't been tested on the production server yet, but I was looking for a cleaner way of structuring the query, as the above doesn't feel very robust, nor does it seem very 'Railsy'.

What I'd like is to be able to say is

Comment.joins(:commentable => :photo)

...but this raises an exception, presumably because Rails doesn't know how to do the join:

ActiveRecord::EagerLoadPolymorphicError: Can not eagerly load the polymorphic association :commentable

I came upon a post on StackOverflow that described a different way of querying a polymorphic association. I was able to come up with the following code based upon this post:

Comment.find_all_by_commentable_type("Upload", :include => :commentable,
        :order => "created_at DESC", :limit => 10)

However, this doesn't work for STI: since Photo is inheriting from Upload, I can't directly fetch the comments pertaining to photos - only the comments for all classes inheriting from Upload.

I've looked at a fair number of other posts relating to either polymorphism or STI, but none combine the two in the way I'm looking for. I could just muddle around with the initial query, but does anyone have any thoughts on alternative ways to structure a query involving polymorphism and STI?

Edit: I found another question on here along the same lines as mine. Unfortunately, the top answer didn't provide the solution I'm looking for. If I were to apply it to my problem I'd be moving the has_many :comments association from the Photo model to the Upload model, and adding some code to the Comment class to determine the correct class of commentable. This isn't ideal as it breaks the modelling in that any subclass of Upload will have comments. There must be a better way...?

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

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

发布评论

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

评论(1

_畞蕅 2024-11-26 01:06:53

您正在提供与 Upload 类的评论的关联。继承自Upload的Photo将通过继承而具有这种关联。由于 comments 方法在 Upload 实例和 Photo 实例上都可用,因此您可以编写以下方法来检索评论:

# app/models/upload.rb

def latest_comments(count=10)
  self.comments.order("created_at DESC").limit(count)
end

在使用 Upload 实例时,这将使用类型“Upload”连接到评论表,当使用该类的实例时,它将使用“照片”类型加入。当遍历评论关联时,Rails 将使用类名自动处理与评论表的连接。

You are providing the association to comments on the Upload class. Photo, which is inheriting from Upload will have this association through inheritance. Since the comments method is available on both the Upload instance, and on the Photo instance, you can write the following method to retrieve the comments:

# app/models/upload.rb

def latest_comments(count=10)
  self.comments.order("created_at DESC").limit(count)
end

This will join to the comments table using the type "Upload" when working with an instance of Upload, and it will join using the type "Photo" when using working with instances of that class. Rails will automatically handle the join to the comments table using the class name when going through the comments association.

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