【问题标题】:Rails Eager loading (includes) and where clause is not working?Rails Eager 加载(包含)和 where 子句不起作用?
【发布时间】:2015-05-28 10:26:19
【问题描述】:

我正在使用 Rails 4.1 和我的模型,例如:

Client has_many TicketLists
TicketList has many projects

现在我正在尝试在客户端模型中使用急切加载,例如:

class Client < ActiveRecord::Base
  def ticket_lists_with_project_id(project_id)
    ticket_lists.includes(:projects).where("projects.id = ?", project_id)
  end  
end  

当我这样做时:

Client.find(2).ticket_lists_with_project_id(1)
  Client Load (1.7ms)  SELECT  "clients".* FROM "clients"  WHERE "clients"."is_destroyed" = 'f' AND "clients"."is_closed" = 'f' AND "clients"."id" = $1 LIMIT 1  [["id", 2]]
PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "projects"
LINE 1: ...d" = 'f' AND "ticket_lists"."client_id" = $1 AND (projects.i...
                                                             ^
: SELECT "ticket_lists".* FROM "ticket_lists"  WHERE "ticket_lists"."is_destroyed" = 'f' AND "ticket_lists"."client_id" = $1 AND (projects.id = 1)
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "projects"
LINE 1: ...d" = 'f' AND "ticket_lists"."client_id" = $1 AND (projects.i...

【问题讨论】:

  • 试试这个:ticket_lists.joins(:projects).where("projects.id = ?", project_id)
  • @Surya 请将此添加为答案,以便我接受。

标签: ruby-on-rails ruby-on-rails-4 activerecord eager-loading


【解决方案1】:

试试下面的:

class Client < ActiveRecord::Base
  def ticket_lists_with_project_id(project_id)
    ticket_lists.includes(:projects)
                .where("projects.id = ?", project_id)
                .references(:projects)
  end  
end

它会起作用的。如果你想 add conditions 到你包含的模型,你必须明确引用它们。另外注意includes 使用关联名称,而references 需要实际的表名。

【讨论】:

  • 国际海事组织,这是正确的答案。我需要includes,而不是joins。感谢references 提示。
  • 根据this guide(参见第 13.2 节),此查询应返回所有ticket_lists,无论它们是否有项目。意思是,应该做一个左外连接。但是,它没有按预期工作。它的行为就像是在进行内部连接。
【解决方案2】:

而不是这个:

ticket_lists.includes(:projects).where("projects.id = ?", project_id)

这样做:

ticket_lists.joins(:projects).where("projects.id = ?", project_id)

由于你使用的是 Rails 4,你可以让它看起来更可爱:

ticket_lists.joins(:projects).where(projects: {id: project_id})

【讨论】:

  • 这太棒了。你是男人。不确定是否使用范围,因为我试图将该方法用作实例方法,而不是您知道的 Client.ticket_lists_for_project 之类的东西。
  • 顺便说一句,在哪里使用包括和在哪里使用连接的任何黄金角色?
【解决方案3】:

这可能会对您有所帮助:

Client.includes(:ticket_lists => :projects).where("clients.id = ? ", 2)

class Client < ActiveRecord::Base
  def ticket_lists_with_project_id(project_id)
    Client.includes(:ticket_lists => :projects).where("projects.id = ?", project_id)
  end  
end 

【讨论】:

  • 他不是在找票单吗?您正在回头客。
  • 感谢您的帮助,如何将其用作实例方法并将其与 'Client.find(2).ticket_lists_with_project_id(1)' 之类的东西一起使用?
  • 我改变了你的实例方法。请检查
  • 确实如此,感谢您的帮助,但我更喜欢 Surya 解决方案,因为涉及的代码更少:P
  • 您检查过这两种解决方案的查询次数吗?
猜你喜欢
  • 2013-03-09
  • 1970-01-01
  • 1970-01-01
  • 2014-03-20
  • 2012-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-27
相关资源
最近更新 更多