標題很混亂,但讓我解釋一下。我有一個車型有多個數據點,具有不同的時間戳。我們幾乎總是關心其最新狀態的屬性。因此模型的has_many狀態,具有HAS_ONE一起輕鬆訪問其最新一個:Rails 3 has_one關聯的一個查詢匹配屬性has_many association的子集
class Car < ActiveRecord::Base
has_many :statuses, class_name: 'CarStatus', order: "timestamp DESC"
has_one :latest_status, class_name: 'CarStatus', order: "timestamp DESC"
delegate :location, :timestamp, to: 'latest_status', prefix: 'latest', allow_nil: true
# ...
end
爲了讓你的狀態保持什麼樣的想法:
loc = Car.first.latest_location # Location object (id = 1 for example)
loc.name # "Miami, FL"
比方說,我想有一個(可鏈接)範圍,找到爲1。最新的位置ID的所有汽車目前我有一種複雜的方法:
# car.rb
def self.by_location_id(id)
ids = []
find_each(include: :latest_status) do |car|
ids << car.id if car.latest_status.try(:location_id) == id.to_i
end
where("id in (?)", ids)
end
有可能做到這一點使用SQL更快的方法,但不知道如何只得到l每輛車的最佳狀態。可能有許多狀態記錄的location_id爲1,但如果這不是其最新的位置,則不應包含它。
爲了讓它更難...讓我們添加另一個級別,並能夠通過位置名稱進行範圍。我有這樣的方法,以及它們的位置對象一起預壓狀態,以便能夠訪問名字:
def by_location_name(loc)
ids = []
find_each(include: {latest_status: :location}) do |car|
ids << car.id if car.latest_location.try(:name) =~ /#{loc}/i
end
where("id in (?)", ids)
end
這將「邁阿密」,「FL」,「MIA」等相匹配的上面的位置...有沒有人有任何建議,我可以如何使這個更簡潔/高效?以不同的方式定義我的關聯會更好嗎?或者,也許它會採取一些SQL忍者技能,我承認沒有。
使用Postgres 9.1(託管在Heroku雪松堆棧上)
我有一種感覺,你的問題的有效解決方案將有點數據庫特定。你能否把你的數據庫的名稱和版本添加到問題中? – MrTheWalrus 2012-08-01 17:40:04
@MrTheWalrus良好的調用,我使用Heroku雪松堆棧與Postgres 9.1 – 2012-08-02 01:22:09
將最新狀態和舊狀態保存在單獨的表中可能會更容易。這樣你仍然有你的歷史,但你沒有困難查詢。有點相關:http://stackoverflow.com/questions/762405/database-data-versioning – Mischa 2012-08-02 02:41:23