2016-02-25 14 views
9

Tôi đang làm thủ công join và tôi cần phải vượt qua một tham số quy định tại khoản ON của nó:parametrized tham gia trong Rails 4

Foo.joins("LEFT OUTER JOIN bars ON foos.id = bars.foo_id AND bars.baz = #{baz}") 

Có cách nào để vượt qua baz như một tham số, để tránh các vấn đề tiêm tiềm năng? Có một phương pháp sanitize_sql_array, nhưng tôi không chắc chắn làm thế nào để sử dụng nó trong trường hợp này.

Lưu ý: Tôi không thể sử dụng where vì nó không giống nhau.

+0

nên baz là một mô hình tham gia? Bạn có thể cho tôi giá trị bạn có cho baz không? –

+0

Vâng, đó sẽ là tuyệt vời để biết những gì baz có thể được. – Kulgar

+0

'baz' là một biến giữ một chuỗi ký tự hoặc một số, ví dụ. Nó không phải là một mô hình khác, đó là một giá trị mà tôi muốn chuyển sang điều kiện ON trong phép nối ngoài. –

Trả lời

8

Với sanitize_sql_array, đó sẽ là:

# Warning: sanitize_sql_array is a protected method, be aware of that to properly use it in your code 
ar = ["LEFT OUTER JOIN bars ON foos.id = bars.foo_id AND bars.baz = %s", baz] 
# Within foo model: 
sanitized_sql = sanitize_sql_array(ar) 
Foo.joins(sanitized_sql) 

thử nó và nó làm việc.

mô hình kỷ lục
+0

@mladenjablanovic - nó có phù hợp với bạn không? – Kulgar

-2

Tôi nghĩ bạn nên cố gắng như thế này:

Foo.joins("LEFT OUTER JOIN bars ON foo.id = bars.foo_id AND bars.baz = ?", baz) 

Với các thông số hơn:

Foo.joins("LEFT OUTER JOIN bars ON foo.id = ? AND bars.baz = ? AND ...", foo, baz, etc...) 
+1

Đây là phương pháp chính xác. –

+5

Thật không may, điều này không hoạt động. 'baz' không được hiểu là giá trị tham số, mà là một mô hình được nối khác. Bạn có thể tự mình thử. https://github.com/rails/rails/blob/9b67cb3d394692aa7feb7510aab0871e557d3dd0/activerecord/lib/active_record/relation/query_methods.rb#L1036 –

+0

Đường AFAIK (ngay cả ở 4.0) không hỗ trợ các tham số trong mệnh đề 'JOIN'. Người ta phải tự tạo ra câu lệnh SQL, như Mladen kết luận. Tôi nghĩ [@Kulgar có quyền] (http://stackoverflow.com/a/35744285/712765) để biết cách làm điều đó một cách an toàn. –

-2

Bạn nên được an toàn nếu bạn vượt qua một hash của các giá trị, AR sẽ bảo vệ bạn chống lại tiêm SQL, như thế này:

Foo.joins("LEFT OUTER JOIN bars ON foo.id = bars.foo_id").where(bars: {baz: baz}) 

Chỉ cần không sử dụng chuỗi hàng trong sql dễ bị chèn ép sql.

+0

Thật không may, không phải những gì tôi muốn. Điều kiện trong WHERE không tương đương với điều kiện trong ON. –

+2

Do tham gia bên ngoài, có điều kiện trong mệnh đề 'JOIN' khác với điều kiện của mệnh đề' WHERE'. Xem http://sqlfiddle.com/#!9/c827b7/5 –

7

kích hoạt có sanitize phương pháp lớp học, vì vậy bạn có thể làm:

Foo.joins("LEFT OUTER JOIN bars ON foos.id = bars.foo_id AND bars.baz = #{Foo.sanitize(baz)}") 
Các vấn đề liên quan