【问题标题】:Update Each Array-Object Value in Rails更新 Rails 中的每个数组对象值
【发布时间】:2016-06-29 17:23:40
【问题描述】:

基本上我想更新 Rails 5 中模型的每个表列。

str = "abc---def"

str.split('---').map do |a|
 Foo.where(product_id:1).update_all(bar: a)
end

旧对象如下:

[
 [0] { product_id: 1,
       ...,
       bar: "xxx",
       ...
     },
 [1] { product_id: 1,
       ...,
       bar: "xxx",
       ...
     }

]

新的应该是这样的:

[
 [0] { product_id: 1,
       ...,
       bar: "abc",
       ...
     },
 [1] { product_id: 1,
       ...,
       bar: "def",
       ...
     }

]

但我得到的是bar: "def"。 rails 中是否有一种干净的方法来实现我想要的? update_attributes 报错。

标题名称正确吗?

【问题讨论】:

  • 首先你的问题不是那么解释。查询 ID(主键)时如何返回多条记录?
  • 让我告诉你我从你的问题中所理解的。所以你说你有一个值数组(在字符串拆分之后)并且你有多个模型对象(在查询之后)并且你希望每个值都以相同的顺序为模型设置,对吧?
  • @QaisarNadeem 谢谢。帖子已更新。
  • 好吧,让我来回答一下

标签: ruby-on-rails ruby loops ruby-on-rails-5


【解决方案1】:

首先让我们从一些基础开始。

您想要更新多行并希望为每一行设置不同的值。所以它不能像你正在做的那样在单个查询中完成。因此,您需要遍历Foo 对象并分别设置每个对象。

让我们假设

str = "abc---def---ghi---jkl"
tokens = str.split('---') 
foos_to_update = Foo.where(product_id: 1) #Let's assume it will return 4 or lesser records. (otherwise you need to tell what do you wanna do if it returns more then `tokens`)
foos_to_update.each_with_index {|foo,i| foo.update(bar: tokens[i])}

最后一行是遍历返回的对象并为每个对象设置bar 值。

【讨论】:

    【解决方案2】:

    首先,使用Foo.where(id:1).update_all 更新单个记录可能有效,但不是惯用的。最好使用Foo.find_by(id: 1).update。对于获取单个记录,我更喜欢使用 find_by 而不是 find,因为它返回 nil 而不是引发 NotFound 错误,但这是个人喜好。

    其次,您使用update_all(bar: a) 的方式会给您带来意想不到的结果。在map 块中,返回值成为结果数组的一部分。 update_all 不返回已更改的记录。它返回一个整数,显示更改的记录数。同样,update 不返回记录。根据验证是否通过,它返回 true 或 false`。

    将这些概念结合起来,可以编写如下代码:

    str = "abc---def"    
    str.split('---').map do |a|
     foo = Foo.find_by(id:1)
     foo&.update(bar: a)
     foo
    end
    
    # note that you could instead write `foo.update(bar: a)` if you
    # don't want to use the safe navigation operator
    

    或者用另一种方式来写它做同样的事情:

    str = "abc---def"
    str.split('---').map do |a|
     Foo.find_by(id:1)&.tap { |foo| foo.update(bar: a) }
    end
    

    请注意,在这些示例中,我使用的是safe navigation operator,它在比2.3 更新的Ruby 版本中。它有助于防止在 nil 对象上出现NoMethodError,但实际上并不是必需的。

    【讨论】:

    • 什么是&.tap? Rails 5 方法?
    • tap 从 1.9 开始就在 Ruby 核心中。这不是必须使用的方法。我认为它的好处主要是风格,增加了可读性。 &. 是我链接的安全导航运算符。
    • 我不得不接受 Qaisar 的回答,因为这对我来说更清楚。然而。你们都没有回答。我已经试过很多次了。最后一个代码从未更新表列。首先在这里遇到语法错误:foo&.update(file_file_name: a)
    • 因为你没有使用 Ruby 2.3。您可以删除&,它会起作用。
    猜你喜欢
    • 2021-07-17
    • 2020-08-11
    • 1970-01-01
    • 2023-01-25
    • 2018-09-25
    • 1970-01-01
    • 2020-04-06
    • 2023-02-13
    • 1970-01-01
    相关资源
    最近更新 更多