Ruby on rails 3 通过附加作用域按关联模型中的列对Rails数据库表进行排序

Ruby on rails 3 通过附加作用域按关联模型中的列对Rails数据库表进行排序,ruby-on-rails-3,Ruby On Rails 3,我不熟悉Rails。我试图在遗留数据库上实现Ryan Bates的可排序表列代码(Railscast#228)。我的问题与“在关联模型中按列对Rails数据库表进行排序”非常相似,但根据那里的答案,我似乎无法解决我的问题 我希望能够按照entityudfstorage表(class Ent)中的udtid对索引视图中的项目列表进行排序,即按照project.Ent.udtid。我还有一个额外的考虑,因为每个项目都匹配许多ent行,所以我需要确定范围以匹配whereent.rowindex!=0

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

我希望能够按照
entityudfstorage
表(class Ent)中的
udtid
对索引视图中的项目列表进行排序,即按照
project.Ent.udtid
。我还有一个额外的考虑,因为每个项目都匹配许多ent行,所以我需要确定范围以匹配where
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")
我一直在试图找出我可以在projecttype的“sort_列”中放入什么,这将使它按相关字段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

非常感谢您的见解!

您实际上并没有说出“不起作用”在本文中的含义。我猜这可能意味着您收到了错误消息,或者项目没有按照您预期的方式排序

如果这是一条错误消息,您应该将其包含在问题中,但我在您的位置上要做的第一件事可能是开始使用Rails约定来命名和引用事物。如果您关联的类是
UserDefinedField
,Rails将期望表命名为
user\u defined\u fields
和assoc>指定为
的字段有很多:用户定义的字段
。它还希望字段是蛇形的(
attach\u to\u id
,而不是
attachtoid
),但除了必须到处指定每个外键之外,这可能不会导致错误。查看您的代码,我希望Rails在加载项目模型时会抱怨关联名称。您应该更改这些内容以匹配约定,或者(如果您有充分的理由使用这些名称),通过在关联中指定类和表名来告诉Rails发生了什么

如果响应顺序不正确,我就不太确定问题出在哪里。一件立即跳出来的事情是,您将得到同一个项目在这个范围内多次返回,每个相关的UserDefinedField返回一次。如果您不希望发生这种情况,您需要在您的范围和一些sor中添加一个
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")
编辑: 看起来您当前的问题是该范围根本没有被使用。以下是可能出现这种情况的几个原因:

  • 我注意到您的控制器操作被称为
    projectscoontroller#list
    ,但是您的日志显示带有参数的请求正在由
    projectscoontroller#index
    处理。对
    list
    操作的调用似乎没有运行任何查询,这听起来好像它没有做任何事情t触发器实际加载对象。这可能只是路由或模板错误吗

  • 假设您说在这两种情况下运行的查询是相同的,那么如果调用了正确的操作,那么您的条件(
    sort\u column==“projecttype”
    )即使在传递参数时也返回false。即使范围不太正确,否则您至少会看到不同的查询。是否可能您只是忘记设置
    sort\u column=params[:sort]
    ?尝试暂时删除条件-始终使用
    @projects=Project.by\u udtid
    。然后查看是否得到其他查询


  • 范围/查询本身的旁注。如果我正确理解您的评论,您希望按照
    Ent
    udtid
    进行排序,并使用最低的非零
    rowindex
    。这将很棘手,详细信息将取决于您的数据库(分组,尤其是复杂的分组,是mySQL和PostGreSQL(Rails应用程序最常见的两种数据库)中工作方式截然不同的一种)。这个概念被称为“groupwise maximum”,您最好的选择可能是结合您的数据库名称搜索该短语。

    谢谢您的反馈TheWalrus先生,我回去编辑了我的原始帖子,希望能澄清这个问题。我正在使用一个遗留数据库,并且我已经在代码中指定了我的外键我相信我得到了正确的范围(字段渲染得很好),但是,我没有在视图中正确实现以获得“排序”在控制器之外。不过,正如您所提到的,我将研究group子句,因为我不想夸大数据库查询。再次感谢!@xyzzy Legacy Database确实是这个行业的一大悲剧。我根据您添加的信息和评论添加了一些建议/想法。我希望它能有所帮助。
    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
    
    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")