Rails 4 .order()被JOINS破坏了

时间:2013-06-28 17:28:46

标签: ruby-on-rails activerecord

我正在努力将现有的Rails 3.2应用程序升级到4.0。不过,我遇到了一堵砖墙。

我有三个型号,客户端,网站和联系人。站点是属于客户端的物理位置,客户端可以有许多站点。联系人是属于一个或多个站点的人员。因此,客户可以通过网站拥有多个联系人。

客户:

class Client < ActiveRecord::Base

  has_many :sites, -> { where(:sites => {:deleted => false}).order(:name => :asc) }, :dependent => :destroy
  has_many :contacts, -> { order(:lastname => :asc) }, :through => :sites

end

站点

class Site < ActiveRecord::Base

  belongs_to :client
  has_and_belongs_to_many :contacts

end

联系人:

class Contact < ActiveRecord::Base

  has_and_belongs_to_many :sites

end

问题在于,当我使用Client.find(1).contacts时,我得到ActiveRecord::StatementInvalid例外:

  

Mysql2 ::错误:'order子句'中的未知列'contacts.name':SELECT contacts。* FROM contacts INNER JOIN contacts_sites ON contacts。{ {1}} = idcontacts_sites INNER JOIN contact_id ON sitescontacts_sites = site_idsites WHERE {{ 1}}。id = 5 AND sitesclient_id = 0 ORDER BY sitesdeleted ASC,contacts。{{1} ASC

有问题:我不知道lastname来自哪里。 Contacts表没有名称列,但Rails正在尝试使用它进行排序,我不知道它来自何处或如何删除它。 contacts很容易;它来自客户端模型。

这些关系在3.2中完美运行,但现在在4.0中抛出此异常。

更新 有人指出额外的name来自客户模型中的第一个ORDER BY ... `contacts`.`name` ASC。但是,目的是对网站进行排序,而不是联系人。我尝试将其更改为ORDER BY `contacts`.`lastname` ASC,并且SQL抱怨没有名为ORDER BY ... `contacts`.`name` ASC的列。因此,当has_many.order('sites.name' => :asc)一起使用时,订单子句会被破坏。

我尝试在网站模型中移除sites.sites.name并使用:through =>,但收到的错误与最初报告的完全相同。

2 个答案:

答案 0 :(得分:9)

解决方案很简单。我没有使用.order(:column_name => :asc),而是将其更改为.order('column_name ASC'),错误消失了,产生了预期的结果。我最初拥有后者,但是实现了前者作为我的Rails 3的一部分 - &gt; 4升级,并在RailsCasts和其他文档中看到了这样的约定。

当使用.joins()并按联接表列排序时,这也是必要的,正如我后来发现的那样。这是有道理的,因为关联也使用连接。

答案 1 :(得分:1)

你必须感到疲倦,就在你的第二行(Client模特),你有 order(:name=> :asc) ,它应该是:

class Client < ActiveRecord::Base

  has_many :sites, -> { where(:sites => {:deleted => false}).order(:lastname => :asc) }, :dependent => :destroy
  has_many :contacts, -> { order(:lastname => :asc) }, :through => :sites

end