【问题标题】:Sort a query based on an association 2 or more levels deep根据 2 级或更多级深的关联对查询进行排序
【发布时间】:2011-08-02 21:51:37
【问题描述】:

我有以下型号

class Post < ActiveRecord::Base
  belongs_to :user, :counter_cache => true
  belongs_to :subtopic      
end


class Subtopic < ActiveRecord::Base
  belongs_to :category
  has_many :posts, :dependent => :destroy
end

class Category < ActiveRecord::Base
  has_many :posts, :through => :subtopics
  has_many :subtopics, :dependent => :destroy
end

在帖子/索引页面中,我想为列标题添加可点击排序。这很好,只是我显示了一些两层深的信息:

  • 帖子属性
    • 子主题名称
      • 类别名称

我希望表格的“类别”列是可点击的,这样我就可以显示所有按类别排序的帖子。不幸的是,当我构造查询的“order by”部分时,我似乎无法为类别名称找到任何东西。我可以深入一层

@posts = Post.includes(:user, :subtopic => :category).paginate(:page =>1, :order => 'subtopics.name ASC')

这会返回我想要的结果。当我尝试更深一层时

@posts = Post.includes(:user, :subtopic => :category).paginate(:page =>1, :order => 'subtopic.categories.name ASC')

我收到PGError: ERROR: schema "subtopic" does not exist。复数子主题给出了同样的错误。我觉得我错过了一些明显的东西。谁能指出来?

旁注:异味警报。我知道。如果您也有关于如何使此代码更清洁的建议,那将非常受欢迎。我知道得墨忒耳法则,但我不知道如何在不破坏它的情况下获得我想要的最终结果。


更新 8/3:ActiveRecord 或 PostgreSQL 在控制器操作中导致另一个错误。以下语句在数据库控制台中有效:
SELECT * from "posts" LEFT OUTER JOIN "users" ON "users"."id" = "posts"."user_id" LEFT OUTER JOIN "subtopics" ON "subtopics"."id" = "posts"."subtopic_id" LEFT OUTER JOIN "categories" ON "categories"."id" = "subtopics"."category_id" ORDER BY categories.name ASC LIMIT 30;

上面的 SQL 语句大约是由下面的语句生成的。下面的 rails 代码在 rails console 中有效,但在我的 Post#index 控制器操作中不是

 @posts = Post.includes(:user, :subtopic => :category).paginate(:page =>1, :order => 'categories.category_name ASC', :conditions => ["posts.flags_count < ?", Flag.flag_threshold] )

错误:https://gist.github.com/1124135

:order =&gt; 'categories. ...':order =&gt; 'subtopics. ...' 会出现此错误,但:order =&gt; (column in posts) 会出现不会。 ActiveRecord 生成的 JOIN 语句看起来有问题,但实际的 SQL 语句看起来应该对我有用。


更新 8/4:当我在我的环境中启用 SQL 日志记录时(使用 a shell script),我可以看到 ActiveRecord 在 rails console 和(一个控制器)中生成的 SQL 查询rails server 不同。

具体来说,在服务器上,AR 会在某些列前添加“post.”,例如 posts.users.display_name 而不是 users.display_name。这只发生在服务器上,并且只有当我在查询中包含:order =&gt; (non-posts column) ASC/DESC

【问题讨论】:

标签: ruby-on-rails activerecord associations


【解决方案1】:

您的 order 子句中的字符串几乎按原样插入到生成的 SQL 中。所以结果查询结果是这样的:

Select...order by subtopic.categories.name ASC

而数据库不知道这意味着什么。您想按“categories.name ASC”订购。

更新:好的,现在 will_paginate 被连接阻塞了。我会这样做:

@posts = Post.includes(:user, :subtopic => :category).where(["posts.flags_count < ?", Flag.flag_threshold]).order('categories.category_name ASC').paginate(:page =>1)

这应该会让你继续前进。我会进一步清理我的控制器,将所有 finder 的东西移到模型中,可能是一个名为“by_category_order”的范围或其他东西。然后我的控制器代码会很好,很像:

@posts = Post.by_category_order.paginate(:page => params[:page])

【讨论】:

  • 谢谢,这是朝着正确方向迈出的一步。我可以让它适用于 SQL 语句。 Ruby 等效项在rails console 中工作,但它在控制器中中断。我用新的错误更新了帖子。
  • 嗯,如果我在控制台中使用where 运行该查询,它工作正常。如果我把它放在我的控制器中,Rails 仍然会被相同的 PGError 阻塞。我什至可以在最后切掉paginate 部分,它也会以同样的方式窒息。这几乎就像rails consolerails server中的数据库之间存在差异......
  • 可能是。他们的 RAILS_ENVs 都在开发吗?
  • 是的,两者都是开发。 Rails.version 在 3.0.9 也相同。我已经能够进一步缩小错误范围——我在帖子中添加了一些细节。
  • 其实,我认为这超出了原问题的范围,所以我会做一个新的,并接受你的回答作为答案。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-31
  • 1970-01-01
  • 1970-01-01
  • 2013-09-28
相关资源
最近更新 更多