2017-04-10 8 views
1

ActiveRecord :: Relationオブジェクトを返すにはfind_by_sqlが必要です。それは不可能であるようです。次に私のクエリを純粋なルビーに書きたい。find_by_sqlからactiveRecordsリレーションを返すもの

私は自分自身との関係を持つテーブルがある:

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が必要です。 :リレーションオブジェクトは結果を処理し続ける必要があるため(ページネーションの宝石を使用し、アレイを用いトン作業)

+0

find_by_sqlのコードは私の問題を解決します。事は、私が結果を使って作業を続ける必要があることです(ページネーションと宝石を使った注文)、この結果はActiveRecord関係でなければなりません。私はSqlの経験がなく、複雑なクエリをレールに入れて、純粋なSQLで左外部結合を行うことができました。レールの方法で書く方法はわかりません。 – Bri4n

+0

@ Bri4n 'Alaram'、' Estado'と 'Relacionada'の関連はなんですか? – Kavincat

+0

もう少し明確になるように私の質問を編集しました。ありがとう@Kavincat – Bri4n

答えて

3

トリックはあなたが生のSQL文の結果のIDを取り、whereを使用して2番目のクエリを実行することであるConverting an array of objects to ActiveRecord::Relation

ので、それは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)) 
+0

これは、すべてのIDをメモリにロードする必要があります。これはむしろ非効率です – teacher