据我所知,arel gem 的当前版本不支持 sql 查询的 FROM 关键字。您可以只使用 SET 和 WHERE 关键字生成查询,例如:
UPDATE t SET t.itty = "b" WHERE ...
对于units 表,将值从field2 复制到field1 的代码如下:
relation = Unit.all
um = Arel::UpdateManager.new(relation.engine)
um.table(relation.table)
um.ast.wheres = relation.wheres.to_a
um.set(Arel::Nodes::SqlLiteral.new('field1 = "field2"'))
ActiveRecord::Base.connection.execute(um.to_sql)
完全可以使用附加方法来更新关系。因此,我们创建了 Arel 的 UpdateManager,为其分配表、where 子句和要设置的值。值 shell 作为参数传递给方法。然后我们需要在生成的SQL请求中添加FROM关键字,我们只有在UPDATE子句本身可以访问指定的外部表时才添加它。最后我们执行查询。所以我们得到:
def update_relation!(relation, values)
um = Arel::UpdateManager.new(relation.engine)
um.table(relation.table)
um.ast.wheres = relation.wheres.to_a
um.set(values)
sql = um.to_sql
# appends FROM field to the query if needed
m = sql.match(/WHERE/)
tables = relation.arel.source.to_a.select {|v| v.class == Arel::Table }.map(&:name).uniq
tables.shift
sql.insert(m.begin(0), "FROM #{tables.join(",")} ") if m && !tables.empty?
# executes the query
ActiveRecord::Base.connection.execute(sql)
end
您可以将关系更新发布为:
values = Arel::Nodes::SqlLiteral.new('field1 = "field2", field2 = NULL')
relation = Unit.not_rejected.where(Unit.arel_table[:field2].not_eq(nil))
update_relation!(relation, values)