2016-02-25 14 views
9

sto facendo manuale join e ho bisogno di passare un parametro alla sua ON clausola:parametrizzate unirsi in Rails 4

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

C'è un modo per passare baz come parametro, per evitare potenziali problemi di iniezione? C'è un metodo sanitize_sql_array, ma non sono sicuro di come utilizzarlo in questo caso.

Nota: non riesco a utilizzare where perché non è lo stesso.

+0

così Baz è un altro modello unito? Puoi darmi il valore che hai per baz? –

+0

Sì, sarebbe bello sapere cosa può essere baz. – Kulgar

+0

'baz' è una variabile che contiene una stringa letterale o un numero, ad esempio. Non è un altro modello, è un valore che voglio passare alla condizione ON nel join esterno. –

risposta

8

Con sanitize_sql_array, che sarebbe:

# 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) 

provato e ha funzionato.

modelli di registrazioni
+0

@mladenjablanovic - funziona per te? – Kulgar

-2

Credo che si dovrebbe provare in questo modo:

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

Con più parametri:

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

Questo è l'approccio corretto. –

+5

Sfortunatamente, questo non funziona. 'baz' non è interpretato come un valore di parametro, ma come un altro modello unito. Puoi provarlo da solo. https://github.com/rails/rails/blob/9b67cb3d394692aa7feb7510aab0871e557d3dd0/activerecord/lib/active_record/relation/query_methods.rb#L1036 –

+0

AFAIK Rails (anche a 4.0) non supporta i parametri in una clausola 'JOIN'. Si deve generare la dichiarazione SQL, come ha concluso Mladen. Penso che [@Kulgar abbia ragione] (http://stackoverflow.com/a/35744285/712765) su come farlo in modo sicuro. –

-2

si dovrebbe essere al sicuro se si passa un hash di valori, AR vi proteggerà contro le iniezioni SQL, in questo modo:

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

Proprio don non utilizzare stringhe di fila in SQL che sono vulnerabili a SQL injection.

+0

Purtroppo, non quello che voglio. La condizione in WHERE non è equivalente alla condizione in ON. –

+2

A causa del join esterno, la condizione nella clausola 'JOIN' è diversa dalla condizione della clausola' WHERE'. Vedi http://sqlfiddle.com/#!9/c827b7/5 –

7

attivi hanno sanitize metodo di classe, in modo che si possa fare:

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