2015-11-10 12 views
16

Geçenlerde Raylar 4.1 ila 4.2 Rails için yükseltilmiş ve yanlışlıkla bu tür alıyoruz çünkü Arel + ActiveRecord kullanarak sorunları görüyoruz:Arel + Raylar 4.2 neden sorunları (bağlamaları kayıp olmak üzere)

ActiveRecord::StatementInvalid: PG::ProtocolViolation: ERROR: bind message supplies 0 parameters, but prepared statement "" requires 8 

İşte kırılıyor kodu: Biz sorgunun ilk bölümünü çözmek için nasıl düşündüm

customers = Customer.arel_table 

     ne_subquery = ImportLog.where(
     importable_type: Customer.to_s, 
     importable_id: customers['id'], 
     remote_type: remote_type.to_s.singularize, 
     destination: 'hello' 
    ).exists.not 

     first = Customer.where(ne_subquery).where(company_id: @company.id) 
     second = Customer.joins(:import_logs).merge(
     ImportLog.where(
      importable_type: Customer.to_s, 
      importable_id: customers['id'], 
      remote_type: remote_type.to_s.singularize, 
      status: 'pending', 
      destination: 'hello', 
      remote_id: nil 
     ) 
    ).where(company_id: @company.id) 

     Customer.from(
     customers.create_table_alias(
      first.union(second), 
      Customer.table_name 
     ) 
    ) 

gibi Customer.where içinde olması exists.not taşıyarak (bağlamaları olmamasından aynı raylar hata içine çalıştıran) öyleyse:

Buçalışır gibiydi ama biz bu kod satırı ile aynı konuda koştu:

first.union(second) 

biz sorguda bu bölümü her çalıştırdığınızda

, bağlamaları kaybolur. Birincisi ve ikincisi aktif kayıt nesneleridir, ama biz onları "birleştirmek" olarak, bağları kaybeder arel nesneleri haline gelir.

Sorgu boyunca bisiklet sürmeyi denedik ve bağlantıları manuel olarak değiştirdik ancak düzgün çalıştığını göremedik. Bunun yerine ne yapmalıyız?

DÜZENLEME: Ayrıca şöyle arel nesnesinde değiştirilmesi elle daha sonra birinci ve ikinci, ve gelen bağlanma değerleri çıkarılarak çalıştı

:

union.grep(Arel::Nodes::BindParam).each_with_index do |bp, i| 
    bv = bind_values[i] 
    bp.replace(Customer.connection.substitute_at(bv, i)) 
end 

Bununla birlikte, başarısız olduğundan,:

NoMethodError: undefined method `replace' for #<Arel::Nodes::BindParam:0x007f8aba6cc248> 

Bu, raylar github repo'da önerilen bir çözümdü.

+0

Bazı sorguların daha iyi yazılabileceğini düşünüyorum (örneğin: second = Customer.joins (: import_logs) .where (import_logs: {/ * ImportLog conditions here * /})) ... başarmaya çalışıyorsun. – muZk

cevap

0

Bu sorunun biraz eski olduğunu biliyorum, ancak hata tanıdık geliyordu. Bir depoda bazı notlar ve çözümümüz vardı, bu yüzden paylaşacağımı düşündüm. biz alıyorduk

hata oldu:

PG::ProtocolViolation: ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1

Yani gördüğünüz gibi, durumumuz biraz farklı. 8 bağlama değerine sahip değildik. Ancak, tek bağımızın değeri hala gizliydi. Genel tutmak için şeylerin isimlerini değiştirdim. Tek bağlama değerine sahip olduğumuz yer burasıdır. Kaybettiğimiz parça bu.

union = first_level.union second_level 
union2 = Comment.from(
    Comment.arel_table.create_table_alias union, :comments 
).union third_level 

relation = Comment.from(Comment.arel_table.create_table_alias union2, :comments) 

Üç farklı soruyu birleştirmemiz gerektiğinden, sizin gibi bir birlik oluşturduk.

Bu noktada kayıp bağlantı değerlerini almak için basit bir ödev yaptık. Sonunda, bu seninkinden biraz daha basit bir dava. Ancak, yararlı olabilir. Bu arada

relation.bind_values = first_level.bind_values 
relation 

, burada bu üzerinde çalışırken bulduğumuz GitHub issue bu. Bu soru yayınlandıktan sonra herhangi bir güncellemeye sahip görünmüyor.

İlgili konular