我々は最近のRails 4.1から4.2レールにアップグレードし、私たちは、このタイプのエラーを取得しているので、AREL + ActiveRecordのを使用しての問題を見ている:AREL + Railsの4.2原因の問題(バインディングが失われて)
ActiveRecord::StatementInvalid: PG::ProtocolViolation: ERROR: bind message supplies 0 parameters, but prepared statement "" requires 8
ここです破壊されたコード:私たちは、クエリの最初の部分を解決する方法を考え出し
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
)
)
は次のようCustomer.where内であることがexists.notを動かすことによって(バインディングを持っていないのと同じレールのバグに実行しています) so:
ne_subquery = ImportLog.where(
importable_type: Customer.to_s,
importable_id: customers['id'],
destination: 'hello'
)
first = Customer.where("NOT (EXISTS (#{ne_subquery.to_sql}))").where(company_id: @company.id)
これは動作するように見えたが、我々はこのコード行と同じ問題に遭遇した:
first.union(second)
我々は、クエリのこの部分を実行するたびに、バインディングが迷子に。 1つ目と2つ目は両方ともアクティブなレコードオブジェクトですが、それらを「結合」するとすぐにバインディングが失われ、arelオブジェクトになります。
クエリをサイクリングして手作業でバインディングを置き換えてみましたが、正しく動作させることができませんでした。代わりに何をすべきですか?
EDIT:
我々はまた、第一及び第二のバインド値を抽出する試み、及び手動のでようARELオブジェクトでそれらを置き換える:
:union.grep(Arel::Nodes::BindParam).each_with_index do |bp, i|
bv = bind_values[i]
bp.replace(Customer.connection.substitute_at(bv, i))
end
しかし、それが原因で失敗します
NoMethodError: undefined method `replace' for #<Arel::Nodes::BindParam:0x007f8aba6cc248>
これはレールgithub repoで提案された解決策でした。
私はいくつかのクエリが書かれていると思います(例:second = Customer.joins(:import_logs).where(import_logs:{/ * ImportLog条件はここにあります/ *}))...あなたは達成しようとしています。 – muZk