基于2个或更多级别的关联对查询进行排序

时间:2011-08-02 21:51:38

标签: ruby-on-rails activerecord associations

我有以下型号

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。多个子主题给出了相同的错误。我觉得我错过了一些明显的东西。有人能说出来吗?

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

<小时/> UPDATE 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 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 => 'categories. ...':order => 'subtopics. ...'发生此错误,:order => (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 => (non-posts column) ASC/DESC

中包含时

1 个答案:

答案 0 :(得分:4)

您的order子句中的字符串几乎按原样插入到生成的SQL中。因此,结果查询结果如下:

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

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

UPDATE :好的,现在will_paginate会阻塞加入。我会做这样的事情:

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

这应该让你去。我会通过将所有查找器内容移动到模型中来进一步清理我的控制器,可能是作为名为“by_category_order”的范围。然后我的控制器代码会很好,很像:

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