【问题标题】:Increment attribute with Arel table使用 Arel 表增加属性
【发布时间】:2018-03-01 13:56:12
【问题描述】:

我想用 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 "

【问题讨论】:

  • 如果您只想增加一个值,您可以在 SQL 中使用UPDATE bars SET foo = foo + 1 执行此操作。所以像set [ [ i[:order], "order + 1" ] ]
  • 这样会好很多,因为你不需要知道应用端的值。
  • 谢谢!但是[ [ i[:order], "order + 1" ] ]发送order = 0我有很多where语句,所以我更喜欢Arel作为sql语句where a = ? and b=? and c=? ...

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


【解决方案1】:

你可以这样做

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

至于阿雷尔:

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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-22
    • 2015-06-12
    • 1970-01-01
    • 2013-05-08
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    • 2012-01-27
    相关资源
    最近更新 更多