使用Arel表增加属性

问题描述 投票:1回答:1

我想用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 "
ruby-on-rails ruby-on-rails-4 arel
1个回答
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。

© www.soinside.com 2019 - 2024. All rights reserved.