gpt4 book ai didi

ruby-on-rails - 分配属性而不覆盖非零数据

转载 作者:行者123 更新时间:2023-12-04 19:53:48 27 4
gpt4 key购买 nike

有没有等价于 assign_attributes没有属性覆盖?

让我用一个简单的例子来解释:

my_model = MyModel.new(first_name: 'Romain', age: nil)

new_attributes = {first_name: 'Pierre', last_name: 'Roger', age: 27}
my_model.assign_attributes(new_attributes)
# What I get : <first_name='Pierre', last_name='Roger', age=27>
# * Romain is overwritten by Pierre
# * nil is overwritten by 27
# What I would like : <first_name='Romain', last_name='Roger', age=27>
# * Romain isn't overwritten by Pierre
# * nil is overwritten by 27

我知道我可以做这样的事情,但它似乎不正确:

new_attributes.merge(
my_model.slice(:first_name, :last_name, :age)
.select { |_, val| !val.nil? }
)
my_model.assign_attributes(new_attributes)

任何的想法?

最佳答案

正如评论中提到的,我认为 ActiveRecord 中没有现成的方法可以做到这一点。但是,您可以编写自己的,甚至更好 - 修改现有的 assign_attributes方法。当然,我们需要格外小心,不要破坏它的基本功能——我们只会稍微扩展它。
assign_attributes方法在 ActiveRecord::AttributeAssignment 中定义模块,然后包含在 ActiveRecord::Base 中.我们可以直接在它的模块中覆盖它,但是编写一个新模块并将其包含在 ActiveRecord::Base 中似乎更简洁。代替(因为我们可以调用super,而不是别名链接)。将以下代码复制到 config/initializers 中的新文件中(任何名字都可以):

module ActiveRecord::AttributeAssignmentOverride
def assign_attributes(new_attributes, options={})
return super(new_attributes) if options.fetch(:override, true)
super(new_attributes.select {|k,_| self[k].nil? })
end
end

class ActiveRecord::Base
include ActiveRecord::AttributeAssignmentOverride
end

然后你可以使用 assign_attributes通常的方式(自然重启后):
model.assign_attributes(new_params)

这将照常工作,覆盖所有非零值。但是,您现在可以添加额外的选项:
 model.assign_attributes(new_params, override: false)

这不会触及已经分配的值。

明白了

上面的代码只适用于 rails 4。Rails 3 使用 attr_accessible而不是用于批量分配安全性的强大参数。这些可能取决于许多条件,因此在 rails 3 默认 assign_attributes方法接受两个参数(与我们的新参数相同)。这意味着您还需要将选项传递给对 super 的每个调用。

关于ruby-on-rails - 分配属性而不覆盖非零数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27817618/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com