【问题标题】:find_by_sql to something that returns an activeRecords relationfind_by_sql 到返回 activeRecords 关系的东西
【发布时间】:2017-09-05 16:53:04
【问题描述】:

我需要 find_by_sql 返回一个 ActiveRecord::Relation 对象。这似乎是不可能的。然后我想用纯红宝石写我的查询。

我有一个与自身有关系的表:

class Alarma < ApplicationRecord
  **belongs_to :root, class_name: "Alarma", foreign_key: "relacionada_id", optional: true
  has_many :children, class_name: "Alarma" , foreign_key: "relacionada_id"**

这是桌子:

create_table "alarmas", force: :cascade do |t|
    t.string   "sysname"
    t.string   "component"
    t.string   "details"
    t.integer  "estado_id"
    t.integer  "relacionada_id"
    t.datetime "created_at",     null: false
    t.datetime "updated_at",     null: false
    t.index ["estado_id"], name: "index_alarmas_on_estado_id", using: :btree
    t.index ["severity_id"], name: "index_alarmas_on_severity_id", using: :btree
  end

这是我在 sql 中的查询:

  Alarma.find_by_sql("SELECT a1.*  FROM alarmas a1 LEFT OUTER JOIN alarmas a2 ON a1.relacionada_id=a2.id 
WHERE a1.estado_id IN (1,2) OR a2.estado_id IN (1,2)")

Alarma 可能是根,然后它有子警报,或者它可能处于状态:estado_id = 2 这意味着它是一个孩子,并且有一个根警报,(这个警报是 relacionada_id)。

例子:

根警报,relacionada_id = null,id = 99 儿童闹钟,relacionada_id = 99,id = 112

我需要的是警报列表,状态为 estado_id = 1 或 2,以及他的根位于状态 estado id 1 或 2 的警报(以及他的状态)

我可以使用 find_by_sql 让它与我自己的 sql 查询一起工作,但它返回一个数组,我需要一个 ActiveRecord::Relation 对象,因为我需要继续处理结果(因为我使用了分页 gem 和 order 和 page方法不适用于数组)

【问题讨论】:

  • find_by_sql 中的代码解决了我的问题。问题是我需要继续处理结果(使用 gem 进行分页和排序),这个结果应该是 ActiveRecord 关系。我没有使用 Sql 的经验,并且在 rails 中有复杂的查询,我可以在纯 sql 中进行左外连接,我不知道如何以 rails 方式编写它。
  • @Bri4n AlaramEstadoRelacionada 之间的关联是什么?
  • 我编辑了我的问题,使其更加清晰。谢谢@Kavincat

标签: ruby-on-rails activerecord


【解决方案1】:

Converting an array of objects to ActiveRecord::Relation

诀窍是您获取原始 SQL 语句结果的 ID,并使用 where 执行第二个查询,因此它返回 ActiveRecord::Relation

as_array = Alarma.find_by_sql("SELECT a1.*  FROM alarmas a1 LEFT OUTER JOIN alarmas a2 ON a1.relacionada_id=a2.id WHERE a1.estado_id IN (1,2) OR a2.estado_id IN (1,2)")

as_relation = Alarma.where(id: as_array.map(&:id))

【讨论】:

  • 这需要你将所有的id加载到内存中,效率相当低
  • 这里的另一个问题是,如果您在原始 sql 中有一些排序,将其转换为 AR 它将使用默认排序范围覆盖它。
猜你喜欢
  • 2012-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
相关资源
最近更新 更多