2015-03-31 19 views
13

farklı yabancı anahtarlar aracılığıyla iki kez, diğer modele Node ait bir model Edge sahip olan dernek masaya katılmak sorgulamak:Raylar takma

def Edge < ActiveRecord::Base 
    belongs_to :first, class_name: 'Node' 
    belongs_to :second, class_name: 'Node' 
end 

Ve ActiveRecord kullanarak bu sorguyu gerçekleştirmek istiyorum:

SELECT * FROM edges INNER JOIN nodes as first ON first.id = edges.first_id WHERE first.value = 5 

Edge.joins(:first) 
:

I .joins() yöntemiyle ilişki katılma yolu bulunan

Ancak bu, bir ilişkilendirme adı değil, bir tablo adı kullanarak sorgu üretir, bu nedenle .where() yönteminde ilişki soyutlamasını kesen tablo adını açıkça kullanmak zorundayım.

Edge.joins('INNER JOIN nodes as first ON nodes.id = edges.first_id') 

Ama bu daha da soyutlama kırar:

Edge.joins(:first).where(nodes: {value: 5}) 

Ben de açıkça modeli takma tanımlamak için .joins() yöntemde SQL sorgusu kullanabilirsiniz.

Katmandaki tablo takma adlarını otomatik olarak tanımlamanın yolu olması gerektiğini düşünüyorum. Ya da belki böyle bir işlevi kendi başıma yazmanın bir yolu. gibi bir şey:

def Edge < ActiveRecord::Base 
    ... 
    def self.joins_alias 
     # Generate something like 
     # joins("INNER JOIN #{relation.table} as #{relation.alias} ON #{relation.alias}.#{relation.primary_key} = #{table}.#{relation.foreign_key}") 
    end 
end 

Ama bunun adı gibi spesifik ilişki, yabancı anahtar hakkında bilgi erişme hakkında herhangi bir bilgi bulamadık vb Peki nasıl yapabilirim?

Ayrıca, Rails'in bile şimdiye kadarki 4. büyük versiyonunda bile böyle belirgin bir özelliğin bu kadar karmaşık olması garip görünüyor. Belki bir şey özlüyorum

cevap

5

Rails 4.2.1'e gelince, ActiveRecord'dan joins'u kullanırken bir takma ad sağlamadığınıza inanıyorum.

Edge.joins(:first).where(nodes: {value: 1}) 
SELECT "edges".* FROM "edges" INNER JOIN "nodes" ON "nodes"."id" = "edges"."first_id" WHERE "nodes"."value" = 1 

Ama her iki düğüm kullanarak sorgulamak zorunda bile, yine de böyle joins kullanabilirsiniz:

ilk düğüm tarafından kenarları sorgulamak istiyorsanız, size ifade ettikleri gibi bunu yapabilirdi

Edge.joins(:first, :second).where(nodes: {value: 1}, seconds_edges: {value: 2}) 
SELECT "edges".* FROM "edges" INNER JOIN "nodes" ON "nodes"."id" = "edges"."first_id" INNER JOIN "nodes" "seconds_edges" ON "seconds_edges"."id" = "edges"."second_id" WHERE "nodes"."value" = 1 AND "seconds_edges"."value" = 2