Chúng tôi vừa mới nâng cấp lên Rails 4.2 từ Rails 4.1 và đang nhìn thấy vấn đề với việc sử dụng Arel + ActiveRecord bởi vì chúng tôi đang nhận được loại lỗi:Arel + Rails 4.2 vấn đề gây (bindings bị mất)
ActiveRecord::StatementInvalid: PG::ProtocolViolation: ERROR: bind message supplies 0 parameters, but prepared statement "" requires 8
Dưới đây là mã được phá vỡ:
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
)
)
Chúng tôi đã tìm ra cách để giải quyết một phần đầu tiên của truy vấn (chạy vào cùng một đường ray lỗi không có ràng buộc) bằng cách di chuyển exists.not được trong vòng Customer.where như như vậy:
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)
Điều này dường như để làm việc nhưng chúng tôi chạy vào cùng một vấn đề với dòng mã này:
first.union(second)
bất cứ khi nào chúng tôi chạy phần này của truy vấn, các ràng buộc bị lạc. đầu tiên và thứ hai là cả hai đối tượng ghi lại hoạt động nhưng ngay sau khi chúng tôi "đoàn kết" chúng, họ mất các ràng buộc được trở thành đối tượng arel.
Chúng tôi đã cố gắng đi xe đạp qua truy vấn và thay thế thủ công các liên kết nhưng dường như không làm cho nó hoạt động bình thường. Thay vào đó chúng ta nên làm gì?
EDIT:
Chúng tôi cũng đã cố gắng trích xuất các giá trị ràng buộc từ đầu tiên và thứ hai, và sau đó tự thay thế chúng trong đối tượng AREL như vậy:
union.grep(Arel::Nodes::BindParam).each_with_index do |bp, i|
bv = bind_values[i]
bp.replace(Customer.connection.substitute_at(bv, i))
end
Tuy nhiên, nó không thành công vì:
NoMethodError: undefined method `replace' for #<Arel::Nodes::BindParam:0x007f8aba6cc248>
Đây là giải pháp được đề xuất trong repo đường ray github.
Tôi nghĩ rằng một số truy vấn có thể được viết tốt hơn (ví dụ: second = Customer.joins (: import_logs) .where (import_logs: {/ * ImportLog conditions here * /})) ... Tôi không hiểu bạn đang cố gắng hoàn thành. – muZk