从不同的模型中选择对象并将它们联合起来

时间:2017-09-21 19:30:06

标签: ruby-on-rails ruby

我必须使用activerecord模型 Model1 and Model2

Model1nameinfo个字段

Model2stateprice

我想创建一个对象数组,它们将是model1 + model2的联合体。 每个sum_model对象都应具有name, info, state, price个属性。

应该是Model1.allModel2.all的总和。例如:

如果Model1.all返回一条name="name" and info ="zz"

的记录

Model2.all会返回state='state' and price=14

的一条记录

model_sum应该是一个包含2个对象的数组:

[{name:'name', info: 'zz', state: '', price: ''}, {name:'', info: '', state: 'state', price: 14}]

我该怎么做?

1 个答案:

答案 0 :(得分:0)

您应该能够通过在Model1Model2之间构建cartesian product(将一个表的每个记录与另一个表的每个表结合起来)来实现您想要实现的目标获取结果模型的属性(其中包含Model1Model2的属性:

Model1
  .joins("CROSS JOIN #{Model2.table_name}")
  .select("#{Model1.table_name}.*, #{Model2.table_name}.*")
  .map(&:attributes) 

为了做到这一点,两个模型之间不需要存在关联。

重新阅读问题并注意到我错过了

之后编辑

您首先必须调整两个模型的选择,以使UNION匹配列。幸运的是,可以在AR语句中添加任意选择,例如

m1 = Model1.select(:name, :info, "'' as state", "'' as price")
m2 = Model2.select(:state, :price, "'' as name", "'' as info")

然后你将不得不手工制作UNION,因为AR不支持。这是由Arel,但我大多数时候怀疑Arel是值得的斗争:

union = Model1.connection.unprepared_statement do
  "((#{m1.to_sql}) UNION (#{m2.to_sql})) AS unioned"
end

然后你可以使用union作为from值来解除select,然后调用每个返回条目的attributes方法来实现你指定的结果:

Model1
  .select('*')
  .from(union)
  .map(&:attributes)