我使用多态关联来跟踪我的项目注释。一切都非常简单的东西。

我的问题是在基于所述多态关联查询和从所述注释模型回到它的主人接合。

因此...

我有一个Comment模型

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

和一个ForumTopics模式:

class ForumTopic < ActiveRecord::Base
  has_many :comments, :as => :commentable
end

我有几个其他“commentable”模式,现在并不重要。 所有这一切工作。

我所试图做的是找到所有属于一个ForumTopic与指定条件的评论(在这种情况下,“特色” ==真)。

当我尝试使用取景器加盟模式:

@comments = Comment.find(:all 
            :joins => :commentable
            :conditions => ["forum_topics.featured = ? ", true] 
            )

我收到以下错误:

  

无法急切装载的多态关联:commentable

使用AR “包括语法”:

@comments = Comment.find(:all 
            :include => :forum_topics
            :conditions => ["forum_topics.featured = ? ", true] 
            )

返回:

  

协会命名 'forum_topics' 没有被发现;也许你拼错了?

如果我尝试,并用一个表名称,而不是关联名(字符串而不是符号)加入:

@comments = Comment.find(:all,
            :joins => "forum_topics",
            :conditions => ["forum_topics.featured = ? ", true] 
            )

予见:

  

Mysql的::错误:未知表 '评论':SELECT评论 FROM评论forum_topics WHERE(forum_topics.featured = 1)*

(你可以在这里看到,基础查询语法是完全关闭和连接全部丢失)。

不知道我在做什么,甚至有可能,也有其他的方式来达到所需的结果,但它似乎是它的的是可行的。

任何想法? 什么我失踪?

有帮助吗?

解决方案

哎呀!

我想我发现这个问题。

当通过加入:

@comments = Comment.find(:all,
        :joins => "forum_topics",
        :conditions => ["forum_topics.featured = ? ", true] 
        )

您需要整个加盟!

:joins => "INNER JOIN forum_topics ON forum_topics.id = comments.commentable_id",

请参阅不断真棒: http://guides.rubyonrails.org/active_record_querying.html#joining-tables

其他提示

一个老问题,但存在由随着多态设置为所述特定类型的直接关联实现这一目标的一个更清洁的方式:

#comment.rb
class Comment < ActiveRecord::Base

  belongs_to :commentable, polymorphic: true
  belongs_to :forum_topics, -> { where( comments: { commentable_type: 'ForumTopic' } ).includes( :comments ) }, foreign_key: 'commentable_id'

  ...

end

您就能够通过:forum_topicsincludes摆脱需要一个凌乱的加入:

@comments = Comment
  .includes( :forum_topics )
  .where( :forum_topics => { featured: true } )

您可以然后进一步通过移动查询转换为范围清理此设置:

#comment.rb
class Comment < ActiveRecord::Base

  ...

  scope :featured_topics, -> { 
    includes( :forum_topics )
    .where( :forum_topics => { featured: true } ) 
  }

  ...

end

更让您能简单地做

@comments = Comment.featured_topics

你需要一个条件,加滑轨3 +

很多人提到它的答案和评论,但我觉得,人,包括我自己,会得到绊倒,如果我在这里登陆,并没有读不够彻底。

所以,这里的正确答案,其中包括有条件的也就是绝对必要的。

@comments = Comment.joins( "INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id" )
                   .where( comments:     { commentable_type: 'ForumTopic' } )
                   .where( forum_topics: { featured:         true         } )

感谢所有人,尤其是@Jits,@Peter和@prograils征求他们的意见。

一旦你介绍有使用“commentable”关联另一个模型接受的解决方案不起作用。 commentable_id不是唯一的,因此你会开始检索了错误的意见。

例如:

您决定添加接受评论的新闻模型......

class News < ActiveRecord::Base
   has_many :comments, :as => :commentable
end

现在你可能会得到两个记录回来,如果你做一个forum_topic评论为1的ID,并使用你的查询1的ID与新闻文章:

:joins => "INNER JOIN forum_topics ON forum_topics.id = comments.commentable_id"

您也许可以通过提供一个commentable_type作为您的条件之一,解决这个问题,但我不认为这是解决这个问题的最佳途径。

我遇到了这篇文章,它会让我的解决方案。使用commentable_type为我的条件之一,但使用LEFT OUTER JOIN代替。没有评论这样的论坛主题将包括在内。

LEFT OUTER JOIN `comments` ON `comments`.`commentable_id` = `forum_topics`.`id` AND `comments`.`commentable_type` = 'ForumTopic'

经过在滑轨工作5

<强>解决方案1:

@comments = Comment
              .where(commentable_type: "ForumTopic")
              .joins("INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id")
              .where(forum_topics: {featured: true})
              .all

<强>解决方案2:

@comments = Comment
              .joins("INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id AND comments.commentable_type = 'ForumTopic'")
              .where(forum_topics: {featured: true}).all

注重原始SQL语法:无反引号是允许的。请参见 http://guides.rubyonrails.org/active_record_querying.html#joining-tables

我个人偏好解决方案1,因为它包含较少的原始的SQL语法。

Rails不包括多态性默认加入,但这种宝石将帮助你加入你轻松多态的关系。 https://github.com/jameshuynh/polymorphic_join

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top