我是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
非常感谢任何洞察力!
答案 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")
编辑: 看起来您当前的问题是范围根本没有被使用。以下是可能出现的几个原因:
我注意到您的控制器操作被称为ProjectsController#list
,但您的日志表明ProjectsController#index
正在处理带参数的请求。对list
操作的调用似乎没有运行任何查询,这听起来似乎没有做任何触发实际加载对象的操作。这可能仅仅是路由或模板错误吗?
鉴于你说在两种情况下运行的查询是相同的,如果正在调用正确的 动作,你的条件(sort_column == "projecttype"
)似乎是即使传递参数,也返回false。即使范围不完全正确,您仍然会在那里看到至少一个不同的查询。您是否可能忘记设置sort_column = params[:sort]
?尝试暂时删除条件 - 只需始终使用@projects = Project.by_udtid
。看看你是否得到了不同的查询。
关于范围/查询本身的附注。如果我正确理解您的评论,您希望按udtid
的{{1}}排序,并使用最低非零Ent
。这将是棘手的,细节将取决于您的数据库(分组,尤其是复杂的分组,是mySQL与PostGreSQL(Rails应用程序的两个最常见的数据库)之间的工作方式之一。)这个概念被称为“groupwise maximum”,你最好的选择可能是与你的数据库名称一起搜索该短语。