假设我在Rails中有一个与使用STI的表相关的关系,就像这样:
class Vehicle < ActiveRecord::Base; end
class Car < Vehicle; end
class Truck < Vehicle; end
class Person < ActiveRecord::Base
has_many :cars
has_many :trucks
has_many :vehicles
end
我想在一次查询中加载一个人及其所有的汽车和卡车,但这种方式不起作用:
# Generates three queries
p = Person.includes([:cars, trucks]).first
...这个很接近,但是没有运气:
# Preloads vehicles in one query
p = Person.includes(:vehicles).first
# and this has the correct class (Car or Truck)
p.vehicles.first
# but this still runs another query
p.cars
我可以在person.rb中做类似以下的操作:
def cars
vehicles.find_all { |v| v.is_a? Car }
end
但是Person#cars
不再是一个集合代理,而我喜欢集合代理。
有没有优雅的解决方案?
编辑:将此添加到Person中可使我使用一个查询获取所需的数组项;这非常接近我想要的:
def vehicle_hash
@vehicle_hash ||= vehicles.group_by {|v|
v.type.tableize
}
end
%w(cars trucks).each do |assoc|
define_method "#{assoc}_from_hash".to_sym do
vehicle_hash[assoc] || []
end
end
现在我可以执行 Person.first.cars_from_hash
(或者为我的非合成用例找到更好的名称)。