使用其他作用域,通过关联模型中的列对Rails数据库表进行排序

时间:2013-08-28 22:57:41

标签: ruby-on-rails-3

我是Rails的新手。我试图在遗留数据库上实现类似Ryan Bates的可排序表列代码(Railscast#228)。我的问题非常类似于“通过关联模型中的列对Rails数据库表进行排序”,但我似乎无法根据那里的答案解决我的问题。

我希望能够通过udtid表(类Ent)中的entityudfstorage对索引视图中的项目列表进行排序,即project.ent.udtid。我有一个额外的考虑因素,因为每个项目都匹配了许多行,所以我需要调整范围以匹配ent.rowindex != 0的位置。

模特:

class Project < ActiveRecord::Base
has_many :ent, :foreign_key => "attachtoid"
has_many :samples, :foreign_key => "projectid"

class Ent < ActiveRecord::Base
set_table_name("entityudfstorage")
belongs_to :project, :foreign_key => "attachtoid"
scope :rowindex, where('entityudfstorage.rowindex != ? ', "0")

项目索引视图:

    <tr>
    <th><%= sortable "name", "Name" %></th>
    <th><%= sortable "projecttype", "Project Type" %> </th>
    </tr>
    <tr>
    <td><%= project.name %></td>
    <td><%= project.ent.rowindex.first.udtid %></td>
    </tr>

项目控制器

def list
@projects = Project.order(sort_column + " " + sort_direction)
end

我一直试图找出我可以在projecttype的“sort_column”中放置什么,它可以通过关联的字段project.ent.rowindex.first.udtid进行排序(与“name”的工作原理相同)在控制器中按project.name排序。

我尝试在

的项目中加入范围
 scope :by_udtids, Project.joins("left join ent on projects.projectid = ent.attachtoid").where('ent.rowindex != ?', 0).order("ent.udtid DESC")

然后在项目控制器中尝试了这个。

if sort_column == "projecttype"
@projects = Project.by_udtids
else
@projects = Project.order(sort_column + " " + sort_direction)

结果是项目索引页面显示了列中的正确数据,但是当我单击“项目类型”链接标题时,它不会排序(而如果我单击“名称”链接标题,它确实排序。我可以在服务器终端看到的日志对于两次点击是相同的,并且查询似乎是正确的。

Started GET "/projects?direction=asc&sort=projecttype" for 128.208.10.200 at 2013-08-29 07:47:52 -0700
Processing by ProjectsController#index as HTML
Parameters: {"direction"=>"asc", "sort"=>"projecttype"}
Project Load (1.5ms)  SELECT "project".* FROM "project" ORDER BY name asc
Ent Load (0.4ms)  SELECT "entityudfstorage".* FROM "entityudfstorage" WHERE "entityudfstorage"."attachtoid" = 602 AND (entityudfstorage.rowindex != '0' ) LIMIT 1
CACHE (0.0ms)  SELECT "entityudfstorage".* FROM "entityudfstorage" WHERE "entityudfstorage"."attachtoid" = 602 AND (entityudfstorage.rowindex != '0' ) LIMIT 1
(0.3ms)  SELECT COUNT(*) FROM "sample" WHERE "sample"."projectid" = 602 
Ent Load (0.3ms)  SELECT "entityudfstorage".* FROM "entityudfstorage" WHERE "entityudfstorage"."attachtoid" = 603 AND (entityudfstorage.rowindex != '0' ) LIMIT 1
CACHE (0.0ms)  SELECT "entityudfstorage".* FROM "entityudfstorage" WHERE "entityudfstorage"."attachtoid" = 603 AND (entityudfstorage.rowindex != '0' ) LIMIT 1
(0.2ms)  SELECT COUNT(*) FROM "sample" WHERE "sample"."projectid" = 603

Rendered projects/list.html.erb within layouts/admin (478.7ms)
Completed 200 OK in 487ms (Views: 398.7ms | ActiveRecord: 87.9ms)
[2013-08-29 07:55:27] WARN  Could not determine content-length of response body. Set content-   length of the response or set Response#chunked = true

Started GET "/assets/jquery.js?body=1" for 128.208.10.200 at 2013-08-29 07:55:28 -0700
Served asset /jquery.js - 304 Not Modified (0ms)
[2013-08-29 07:55:28] WARN  Could not determine content-length of response body. Set content-   length of the response or set Response#chunked = true

非常感谢任何洞察力!

1 个答案:

答案 0 :(得分:0)

在这种情况下,你实际上并没有说“不起作用”是什么意思。我猜这或者意味着你得到一条错误消息,或者项目没有按照你期望的方式排序。

如果这是一条错误消息,你应该把它包含在你的问题中,但我要做的第一件事就是开始使用Rails约定来命名和引用事物。如果关联的类是UserDefinedField,则Rails将期望将表命名为user_defined_fields,并将关联指定为has_many :user_defined_fields。它还希望 fields 处于蛇形(attach_to_id,而不是attachtoid),但除了必须在每个地方指定每个外键之外,这可能不会导致错误。看看你的代码,我希望Rails在加载Project模型的任何时候都会抱怨关联名称。您应该更改这些内容以符合约定,或者(如果您有充分的理由使用这些名称),通过在关联中指定类和表名来告诉Rails是什么。

如果这是一个不正确的响应顺序,我不太清楚问题是什么。立即跳出的一件事是,您将使用此范围多次返回相同的Project,每个关联的UserDefinedField一次。如果您不希望这种情况发生,则需要在范围中添加group子句,并为userdefinedfields.udtids添加某种聚合。这可能类似于:

scope :by_udtids, Project.
  joins("left join userdefinedfields on projects.projectid = userdefinedfields.attachtoid").
  where('userdefinedfields.rowindex != ?', 0).
  group('projects.id').
  order("max(userdefinedfields.udtid) DESC")

编辑: 看起来您当前的问题是范围根本没有被使用。以下是可能出现的几个原因:

  1. 我注意到您的控制器操作被称为ProjectsController#list,但您的日志表明ProjectsController#index正在处理带参数的请求。对list操作的调用似乎没有运行任何查询,这听起来似乎没有做任何触发实际加载对象的操作。这可能仅仅是路由或模板错误吗?

  2. 鉴于你说在两种情况下运行的查询是相同的,如果正在调用正确的 动作,你的条件(sort_column == "projecttype")似乎是即使传递参数,也返回false。即使范围不完全正确,您仍然会在那里看到至少一个不同的查询。您是否可能忘记设置sort_column = params[:sort]?尝试暂时删除条件 - 只需始终使用@projects = Project.by_udtid。看看你是否得到了不同的查询。

  3. 关于范围/查询本身的附注。如果我正确理解您的评论,您希望按udtid的{​​{1}}排序,并使用最低非零Ent。这将是棘手的,细节将取决于您的数据库(分组,尤其是复杂的分组,是mySQL与PostGreSQL(Rails应用程序的两个最常见的数据库)之间的工作方式之一。)这个概念被称为“groupwise maximum”,你最好的选择可能是与你的数据库名称一起搜索该短语。