简体   繁体   English

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

[英]Rails: Structuring a query involving a polymorphic association and STI

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.我正在尝试查找关于照片的 10 条最新评论,以便我可以将它们集成到我的 Rails 3.0.3 应用程序的活动源中。

I've got a Photo model, which inherits from an Upload model using single table inheritance:我有一张照片model,它继承自上传model,使用单表 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:注释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:经过反复试验,我想出了位于照片 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.这段代码可以在我的开发机器上使用 SQLite,但我必须进行一些更改才能让它在使用 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'.查询的上述化身尚未在生产服务器上进行测试,但我正在寻找一种更简洁的方式来构建查询,因为上面感觉不是很健壮,也不是很“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: ...但这引发了一个异常,大概是因为 Rails 不知道如何进行连接:

ActiveRecord::EagerLoadPolymorphicError: Can not eagerly load the polymorphic association:commentable 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.在 StackOverflow 上看到一篇文章,描述了一种查询多态关联的不同方式。 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.但是,这不适用于 STI:由于 Photo 是从 Upload 继承的,我无法直接获取与照片有关的评论 - 只能获取从 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.我查看了相当多与多态性或 STI 相关的其他帖子,但没有一个以我正在寻找的方式将两者结合起来。 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?我可以对最初的查询感到困惑,但是有人对构建涉及多态性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 . 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.这并不理想,因为它破坏了 Upload 的任何子类都会有注释的建模。 There must be a better way...?一定会有更好的办法...?

You are providing the association to comments on the Upload class.您正在为上传 class 上的评论提供关联。 Photo, which is inheriting from Upload will have this association through inheritance.从 Upload 继承的照片将通过 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:由于评论方法在 Upload 实例和 Photo 实例上都可用,您可以编写以下方法来检索评论:

# 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.这将在使用 Upload 实例时使用“Upload”类型加入评论表,当使用 class 的实例时,它将使用“Photo”类型加入。 Rails will automatically handle the join to the comments table using the class name when going through the comments association.在通过评论关联时,Rails 将使用 class 名称自动处理评论表的连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM