标题令人困惑,但请允许我解释一下。我有一个具有不同时间戳的多个数据点的汽车模型。我们几乎总是关心其最新状态的属性。所以模型 has_many 状态,以及一个 has_one 可以轻松访问它的最新状态:
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"
假设我想要一个(可链接的)范围来查找最新位置 id 为 1 的所有汽车。目前我有一种复杂的方法:
# 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 可能有更快的方法来执行此操作,但不确定如何仅获取每辆车的最新状态。可能有许多 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
这将使上面的位置与“miami”、“fl”、“MIA”等相匹配……有人对我如何使它更简洁/高效有任何建议吗?以不同的方式定义我的关联会更好吗?或者可能需要一些我承认没有的 SQL 忍者技能。
使用 Postgres 9.1(托管在 Heroku cedar 堆栈上)