我如何 "resuse" Arel 中的单个绑定变量?

How do I "resuse" a single bind variable in Arel?

我想以编程方式创建此SQL,使用 Arel 的单个绑定参数:

"users"."first_name" ILIKE  OR "users"."last_name" ILIKE 

我试过:

users = Arel::Table.new("users")
term = Arel::Nodes::BindParam.new("term") # what is the argument even used for?
users[:first_name].matches(p)
                  .or(
                     users[:last_name].matches(p)
                   )

但它会产生两个不同的绑定变量:

("users"."first_name" ILIKE  OR "users"."last_name" ILIKE )

有没有办法做到这一点,或者我应该只使用 Arel::Nodes::SqlLiteral.new("") 而不是 BindParam

BindParam 总是 auto-increments 绑定变量,与参数无关。这里添加bind节点时

https://github.com/rails/rails/blob/v7.0.2.3/activerecord/lib/arel/visitors/to_sql.rb#L746

def visit_Arel_Nodes_BindParam(o, collector)
  collector.add_bind(o.value, &bind_block) # o.value # => 'term'
end

最终值仅来自 auto-incremented @bind_index 这里

https://github.com/rails/rails/blob/v7.0.2.3/activerecord/lib/arel/collectors/sql_string.rb#L15

def add_bind(bind) # bind # => 'term'
  self << yield(@bind_index)
  @bind_index += 1
  self
end

BindParam 参数此时未使用。当构建完整的 ActiveRecord 查询时涉及其他收集器时使用它,例如 Arel::Collectors::SubstituteBinds https://github.com/rails/rails/blob/v7.0.2.3/activerecord/lib/arel/collectors/substitute_binds.rb#L18

def add_bind(bind)
  bind = bind.value_for_database if bind.respond_to?(:value_for_database)
  self << quoter.quote(bind)
end

没有制作自定义收集器 class 除了 Arel::Nodes::SqlLiteral.new("") 我没有看到任何其他选项。