Ruby on Rails 通过多个连接表访问数据

Ruby on Rails access data through multiple joining tables

我有 5 个表(最简单的减少),中间有 3 个表。

       /   sample   \
      |              |
chart -   compound   -  results
      |              |
       \ run_method /

每个图表都有一个样品、化合物和 run_method。

每个结果都有一个样品、化合物和 run_method。

我想获得与图表的 3 个连接相匹配的所有结果...

最简单的方法是什么?

class Chart < ApplicationRecord
  belongs_to :sample, inverse_of: :charts
  belongs_to :compound, inverse_of: :charts
  belongs_to :run_method, inverse_of: :charts
end

class Result < ApplicationRecord
  belongs_to :sample, inverse_of: :results
  belongs_to :compound, inverse_of: :results
  belongs_to :run_method, inverse_of: :results
end

class Sample < ApplicationRecord
  has_many :results, inverse_of: :sample
  has_many :charts, inverse_of: :compound
end

etc.

我尝试过使用 Arel 来获取数据:

chart = Chart.arel_table
results = Result.arel_table
run_method = RunMethod.arel_table
sample = Sample.arel_table
compound = Compound.arel_table

results_join = results.join(sample).on(results[:sample_id].eq(sample[:id]))
                      .join(compound).on(results[:compound_id].eq(compound[:id]))
                      .join(run_method).on(results[:run_method_id].eq(run_method[:id]))
                      .join(chart).on(chart[:sample_id].eq(sample[:id])
                                      .and(chart[:compound_id].eq(compound[:id]))
                                      .and(chart[:run_method_id].eq(run_method[:id])))
@allresults = Result.joins(results_join.join_sources)
  .where(chart[:id].eq(params[:id]))

这得到了预期的值,但现在显然没有实际使用 ActiveRecord 模型,因此遗漏了任何默认范围。

在我添加的图表模型中:

has_many :results, -> { where('results.run_method_id = run_methods.id and results.compound_id = compounds.id') }, through: :sample

我可以使用以下方法获取数据:

Chart.joins(:run_method).joins(:compound).includes(:run_method).includes(:compound).joins(:results).includes(:results).first.results

但这仍然没有实际使用模型之间的连接(示例除外)。

有没有办法在 ActiveRecord 和模型中做到这一点?

我最终创建了一个 def 调用图表模型中的结果对象:

在chart.rb中:

def results
  Result.where(compound: compound, run_method: run_method, sample: sample)
end

它有效,而且速度很快,不需要大量的 Arel 或记住要 include/join 的最少表格。

我不需要反转“连接”,所以我认为这是安全的。