使用.includes方法usind send()后Rails访问列

时间:2018-03-26 06:42:31

标签: ruby-on-rails activerecord

这是我使用includes =>

的基本查询
result = Table1.where(some_condition).includes(:table2).where(some_condition)

现在我可以双向访问table1列:

result[0]['table1_column'] ,

result[0].table1_column, 

name = 'table1_column'

result[0].send(name)

上述所有作品实际上都包含这些列。 但是table2列仅在内存中通过急切加载,因此我无法通过以下方式访问它们:

result[0].table2_column ,

name = 'table2_column'

result[0].send(name)

以上都不起作用,我需要使用发送

来访问它们

2 个答案:

答案 0 :(得分:0)

解决方案:

result[0].table_2.table2_column

或者特别是因为您想使用.send(),然后:

result[0].table_2.send('table_2_column')

说明:

我不确定这是否是标准,但据我所知,你不应该对待......

Table1.where(some_condition).includes(:table2).where(some_condition)

...好像它在SQL中返回类似结果(即结果的二维表),而是将结果视为Rails对象(模型而不是表)。请考虑以下事项:

result1 = Model1.where(some_condition)
puts result1.class
# => Model1::ActiveRecord_Relation
puts result1[0].class
# => Model1
puts result1[1].class
# => Model1
# ...

result2 = Model2.where(some_condition)
puts result2.class
# => Model2::ActiveRecord_Relation
puts result2[0].class
# => Model2
puts result2[1].class
# => Model2
# ...

result3 = Model1.includes(:model2).where(some_condition)
puts result3.class
# => Model1::ActiveRecord_Relation
puts result3[0].class
# => Model1
puts result3[1].class
# => Model1
# ...
  • 您可能会注意到result1Model1的“列表”,与预期相同,result2也是如此。但是,在result3注意到即使它是一个“include”子句(LEFT OUTER JOIN),结果仍然会被视为Model1,而不是“连接列”结果。< / LI>

替代解决方案:

鉴于你想要使用.send(),如果你真的想要做...

result[0].send('table2_column')

......而不是......的标准方式。

result[0].table_2.send('table2_column')

然后您可以使用delegate。但请注意,这是模型的全局配置,而不是查询结果特定的配置。

class Model1 < ApplicationRecord
  belongs_to :model2
  delegate :table2_column, to: :model2
end

然后你现在可以......

result3 = Model1.includes(:model2).where(some_condition)
puts result3[0].table2_column
# or specifically as per your requirement:
puts result3[0].send('table2_column')

答案 1 :(得分:0)

您无法使用includes对象上的Table1访问它们,为此您需要编写手动选择查询。

如果您考虑一下,您告诉AR从Table1获取行(从而填充对象类型Table1的集合),并且您希望它包含在来自Table2的对象列中没有意义。

如果您绝对需要这样做,可以使用ActiveRecord::Base.connection执行手动查询:

results = ActiveRecord::Base.connection.exec_query 'SELECT table1.*, table2.* FROM table1 INNER JOIN table2 ON table1.pkey = table2.fkey WHERE condition;'

然后,您可以使用结果集来选择列:

results.first['column_from_table_2']