Rails急切加载字段匹配父字段?

时间:2014-06-16 07:27:50

标签: sql ruby-on-rails activerecord models

我正在尝试加载模型,我试图加载单个记录。

让我们说:

Customer.includes(:sales).where('sales.created_at' => 'customer.last_sale_at')

但不是使用SQL WHERE:

... WHERE "sales"."created_at" = "customer"."last_sale_at"

 count 
-------
  1990
(1 row)

rails生成无效:

... WHERE "sales"."created_at" = 'customer.last_sale_at'

ERROR:  invalid input syntax for type timestamp: "last_sale_at"
LINE 1: ...d" = "customers"."id" WHERE "sales"."created_at" = 'last_sale...

我也尝试过:

Customer.includes(:sales).where('sales.created_at' => '"customer"."last_sale_at"')
Customer.includes(:sales).where('sales.created_at' => :last_sale_at)
Customer.includes(:sales).where('"sales"."created_at" = "customer"."last_sale_at"')

产生了各种各样的错误。

怎么了?

编辑:我将问题更新为更加不言自明。

3 个答案:

答案 0 :(得分:1)

您应该传递日期对象而不是' last_sale_at',它应该是类似下面的内容,

Customer.includes(:sales).where('sales.created_at' => Time.now)

答案 1 :(得分:0)

如果你看错误

ERROR: invalid input syntax for type timestamp: "last_sale_at"

它清楚地表明您的查询中存在语法错误。活动记录期望它是日期时间,因为您的 sales.created_at是时间戳,并且您将其作为字符串或其他非日期时间类型的类型提供。您需要传入日期对象才能使查询正常工作。

<强> FIX

您需要确保 last_sale_at 字段属于datetime

答案 2 :(得分:0)

使用“includes”时无法调用条件,因为记录在单独的查询中被急切加载。您需要使用连接:

Customer.joins(:sales).where('sales.created_at = customers.last_sale_at')

话虽这么说,我建议你使用一个稍微不同的架构,你在客户上建立一个指向最后一笔销售的实际关系,I.E an foreign_key'last_sale_id'。

class Customer < ActiveRecord::Base
  has_many :sales
  belongs_to :last_sale, class_name: 'Sale'
end

创建销售时,您可以在回调中更新客户last_sale:

class Sale < ActiveRecord::Base
  after_create :update_customers_last_sale

  private

  def update_customers_last_sale
    customer.last_sale = self
    customer.save!
  end
end

使用该结构,您可以执行此操作以加载所有客户的上一次销售:

Customer.includes(:last_sale)