参数化加入 Rails 4

Parametrized join in Rails 4

我正在做手册 join,我需要将参数传递给它的 ON 子句:

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

有没有办法将 baz 作为参数传递,以避免潜在的注入问题?有一种方法 sanitize_sql_array,但我不确定在这种情况下如何使用它。

注意:我不能使用where,因为它不一样。

我认为你应该这样尝试:

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

更多参数:

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

如果您传递值的哈希值,您应该是安全的,AR 将保护您免受 SQL 注入,如下所示:

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

只是不要在 sql 中使用易受 sql 注入攻击的行字符串。

如果是 sanitize_sql_array,那就是:

# Warning: sanitize_sql_array is a protected class 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 a class method in foo model:
sanitized_sql = sanitize_sql_array(ar)
Foo.joins(sanitized_sql)

试过了,成功了。

活动记录模型有 sanitize class 方法,所以你可以这样做:

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

__

它已从 rails 5.1 开始删除,请改用 ActiveRecord::Base.connection.quote()

A​​rel 可以做到。

baz = "i am a baz"
foos = Arel::Table.new('foos') # or Foo.arel_table, if this is an AR model
bars = Arel::Table.new('bars')
join = foos.outer_join(bars).on(
  foos[:id].eq(bars[:foo_id]),
  bars[:baz].eq(baz))
puts join.to_sql

这会产生

SELECT FROM "foos"
LEFT OUTER JOIN "bars" ON
  "foos"."id" = "bars"."foo_id"
  AND "bars"."baz" = 'i am a baz'

现在,如果您想将其返回到 ActiveRecord 查询中,而不仅仅是打印 SQL:

Foo.joins(join.join_sources)