【问题标题】:How to get data from 2 tables via active record in rails如何通过rails中的活动记录从2个表中获取数据
【发布时间】:2020-01-27 20:34:34
【问题描述】:

我无法理解 Rails Active Record 的逻辑。

我有 2 个模型:

  • WSDL
  • 状态
# wdsl
class Wsdl < ApplicationRecord
  has_one :status
  validates :mis_url, presence: true
  validates :short_name, presence: true
end

# status
class Status < ApplicationRecord
  belongs_to :wsdl
end

数据库中的表:

我正在通过程序(不是 ActiveRecord 和 Rails)进行简单的 SQL 查询,如您所见,每条记录中有 9 列:


但是,如果我通过 Active Record 执行此查询,我会在每个“记录”中得到一个包含“3 列”的对象:


如您所见,查询是相等的,但我得到的数据没有“状态”模型。

PS 我无法真正修改“Wsdls”表 - 我真的需要“Statuses”表,而且我不想在 Rails 中使用原始 SQL 查询从两个表中获取数据。

我做错了什么?

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    ActiveRecord 关系 joins 用于编写复杂查询,但模型仅从其自己的表中加载属性(除非您编写类似 .select('statuses.code as attr_name_for_code, wsdls.*') 的内容)

    您可以使用.joins(:status).includes(:status) 预先加载关联,rails 将使用两个模型本身的所有字段构造select ... from ... join ...,并且wsdl.status 对象将已经加载。

    【讨论】:

      【解决方案2】:

      在 Rails 中 .joins 主要用于在连接表上应用条件:

      Wsdl.joins(:status).where(statuses: { code: 99 })
      

      由于这会创建一个内部连接,因此只会返回来自地址匹配的用户的行。

      您还可以将 .joins.left_joins (Rails 5+) 与自定义选择一起使用,以从联接表中选择聚合或列。

      Wsdl.joins(:status).select('wsdl.*', 'status.code as status_code')
      
      # Using a LEFT OUTER JOIN instead of INNER will return rows with no status
      Wsdl.left_joins(:status).select('wsdl.*', 'status.code as status_code')
      

      如果您想加载模型实例并避免 N+1 查询问题,请改用 .includes.eager_load。不同之处在于.eager_load 会预先加载所有内容,而.includes 会尝试智能并仅在需要时才加载。

      # This will load all the records and the assocation at once
      @wsdls = Wsdl.eager_load(:status)
      @wsdls.each do |object|
        # this would cause a N+1 query if we didn't eager load.
        puts object.status.code
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-30
        • 2013-12-11
        • 1970-01-01
        • 2017-01-06
        • 1970-01-01
        相关资源
        最近更新 更多