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

Eri*_* Hu 6 activerecord ruby-on-rails 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
Run Code Online (Sandbox Code Playgroud)

在帖子/索引页面中,我想为列标题添加可点击排序.这很好,除了我显示两个级别的一些信息:

  • 发布属性
    • 副主题名称
      • 分类名称

我希望表格的"类别"列可以点击,这样我就可以显示按类别排序的所有帖子.不幸的是,当我构建查询的"order by"部分时,我似乎无法为类别名称工作.我可以深入一级

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

这将返回我想要的结果.当我尝试更深入一级时

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

我得到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;
Run Code Online (Sandbox Code Playgroud)

上面的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] )
Run Code Online (Sandbox Code Playgroud)

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

对于出现此错误:order => 'categories. ...':order => 'subtopics. ...',但:order => (column in posts).它似乎是ActiveRecord生成的JOIN语句的问题,但实际的SQL语句看起来应该对我有用.


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

具体来说,在服务器上,AR正在使用"post."前置某些列,例如posts.users.display_name代替users.display_name.这只发生在服务器上,并且仅在我包含在查询中时才会发生:order => (non-posts column) ASC/DESC

Jof*_*din 4

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

Select...order by subtopic.categories.name ASC
Run Code Online (Sandbox Code Playgroud)

数据库不知道这意味着什么。您想按“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)
Run Code Online (Sandbox Code Playgroud)

这应该能让你继续前进。我将通过将所有查找器内容移动到模型中来进一步清理我的控制器,可能作为名为“by_category_order”或其他名称的范围。那么我的控制器代码就会很好,如下所示:

@posts = Post.by_category_order.paginate(:page => params[:page])
Run Code Online (Sandbox Code Playgroud)