使用Arel表增加属性

时间:2018-03-01 13:56:13

标签: ruby-on-rails ruby-on-rails-4 arel

我想用arel_table增加一个值 我试试这个

update_manager = Arel::UpdateManager.new(ActiveRecord::Base)
i = Arel::Table.new(:items)
update_manager.table(i)
update_manager.where(i[:id].not_eq(id)).
   set [ [ i[:order], i[:order] + 1 ] ]

但update_manager.to_sql返回:

"UPDATE \"items\" SET \"order\" = NULL"

我该怎么办?

set [ [ i[:order], i[:order] ] ]

我得到了

"UPDATE \"items\" SET \"order\" = \"items\".\"order\""

set [ [ i[:order], 1 ] ]

我得到了

"UPDATE \"items\" SET \"order\" = 1 "

1 个答案:

答案 0 :(得分:0)

你可以做到

Item.where.not(id: id).where(a: a, b: b, c: c).update_all('order = order + 1')

至于Arel:

i[:items] + 1
# => #<Arel::Nodes::Grouping:0x000000074152d8 @expr=#<Arel::Nodes::Addition:0x00000007415300 @left=#<struct Arel::Attributes::Attribute relation=#<Arel::Table:0x000000074805b0 @name="items", @engine=ActiveRecord::Base, @columns=nil, @aliases=[], @table_alias=nil, @primary_key=nil>, name=:items>, @right=1, @operator=:+>>

它看起来像一个合理的Arel::Nodes::Grouping,也是

(i[:items] + 1).to_sql
# => "(\"items\".\"items\" + 1)"

事实上

set [ [ i[:order], i[:order] + 1 ] ]

结果

SET \"order\" = NULL

看起来更像是Arel中的一个错误。

如果您将(i[:items] + 1).to_sql的结果传递给更新管理器

,请参阅
update_manager.set [ [ i[:order], (i[:order] + 1).to_sql ] ]

然后它将作为要分配的字符串值传递给SQL查询,而不是作为表达式(有意义):

UPDATE \"items\" SET \"order\" = '(\"items\".\"order\" + 1)'

因此您需要编写一些额外的处理(例如,获取生成的sql字符串,切断这些引号,执行生成的sql)。但我个人认为ActiveRecord代替Arel

另外,您可能需要查看Squeel gem。