Reputation: 561
I'm trying to eager load a model where I try to eager load a single record.
Let's say:
Customer.includes(:sales).where('sales.created_at' => 'customer.last_sale_at')
but instead of working SQL WHERE:
... WHERE "sales"."created_at" = "customer"."last_sale_at"
count
-------
1990
(1 row)
rails produces invalid:
... 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...
I also tried:
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"')
which produced variety of errors.
What's wrong?
EDIT: I updated the question to be more self-explanatory.
Upvotes: 0
Views: 155
Reputation: 5847
You can't call conditions when using "includes" because the records are being eager loaded in a separate query. You need to use a join instead:
Customer.joins(:sales).where('sales.created_at = customers.last_sale_at')
That being said, I suggest you use a slightly different architecture where you you create an actual relation on customer that points to the last sale, I.E a foreign_key 'last_sale_id'.
class Customer < ActiveRecord::Base
has_many :sales
belongs_to :last_sale, class_name: 'Sale'
end
When a sale is created you can update the customers last_sale in a callback:
class Sale < ActiveRecord::Base
after_create :update_customers_last_sale
private
def update_customers_last_sale
customer.last_sale = self
customer.save!
end
end
With that structure you can do this to load all customers with their last sale:
Customer.includes(:last_sale)
Upvotes: 0
Reputation: 9173
If you look at your error
ERROR: invalid input syntax for type timestamp: "last_sale_at"
It clearly states that there's a syntax error in your query. Active record is expecting it to be of date time as your sales.created_at is a timestamp and you are suppling it as a string or some other type which is not of datetime type. You need to pass in a date object to get your query working.
FIX
You need to make sure that your last_sale_at field is of datetime
Upvotes: 0
Reputation: 4200
You should pass date object instead of 'last_sale_at', it should be something like below,
Customer.includes(:sales).where('sales.created_at' => Time.now)
Upvotes: 1