Rails 创建或更新魔法? [英] Rails create or update magic?

查看:10
本文介绍了Rails 创建或更新魔法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 CachedObject 的类,它存储由键索引的通用序列化对象.我希望这个类实现一个 create_or_update 方法.如果找到一个对象,它会更新它,否则它会创建一个新的.

有没有办法在 Rails 中做到这一点,还是我必须编写自己的方法?

解决方案

Rails 6

Rails 6 添加了一个 upsertupsert_all 提供此功能的方法.

Model.upsert(column_name: value)

<块引用>

[upsert] 它不会实例化任何模型,也不会触发 Active Record 回调或验证.

轨道 5、4 和 3

如果您正在寻找upsert"(数据库在同一操作中执行更新或插入语句)类型的语句,则不会.开箱即用,Rails 和 ActiveRecord 没有这样的功能.但是,您可以使用 upsert gem.

否则,您可以使用:find_or_initialize_byfind_or_create_by,它提供了类似的功能,但代价是额外的数据库访问,在大多数情况下,这根本不是问题.所以除非你有严重的性能问题,否则我不会使用 gem.

例如,如果没有找到名为Roger"的用户,则会实例化一个新用户实例,并将其 name 设置为Roger".

user = User.where(name: "Roger").first_or_initializeuser.email = "email@example.com"用户保存

或者,您可以使用 find_or_initialize_by.

user = User.find_or_initialize_by(name: "Roger")

在 Rails 3 中.

user = User.find_or_initialize_by_name("Roger")user.email = "email@example.com"用户保存

您可以使用块,但该块仅在记录是新记录时运行.

User.where(name: "Roger").first_or_initialize do |user|# 如果找到名为Roger"的用户,这将不会运行用户保存结尾User.find_or_initialize_by(name: "Roger") do |user|# 如果找到名为Roger"的用户,这也不会运行用户保存结尾

如果你想使用块而不考虑记录的持久性,使用 点击结果:

User.where(name: "Roger").first_or_initialize.tap do |user|user.email = "email@example.com"用户保存结尾

I have a class called CachedObject that stores generic serialized objects indexed by a key. I want this class to implement a create_or_update method. If an object is found it will update it, otherwise it will create a new one.

Is there a way to do this in Rails or do I have to write my own method?

解决方案

Rails 6

Rails 6 added an upsert and upsert_all methods that deliver this functionality.

Model.upsert(column_name: value)

[upsert] It does not instantiate any models nor does it trigger Active Record callbacks or validations.

Rails 5, 4, and 3

Not if you are looking for an "upsert" (where the database executes an update or an insert statement in the same operation) type of statement. Out of the box, Rails and ActiveRecord have no such feature. You can use the upsert gem, however.

Otherwise, you can use: find_or_initialize_by or find_or_create_by, which offer similar functionality, albeit at the cost of an additional database hit, which, in most cases, is hardly an issue at all. So unless you have serious performance concerns, I would not use the gem.

For example, if no user is found with the name "Roger", a new user instance is instantiated with its name set to "Roger".

user = User.where(name: "Roger").first_or_initialize
user.email = "email@example.com"
user.save

Alternatively, you can use find_or_initialize_by.

user = User.find_or_initialize_by(name: "Roger")

In Rails 3.

user = User.find_or_initialize_by_name("Roger")
user.email = "email@example.com"
user.save

You can use a block, but the block only runs if the record is new.

User.where(name: "Roger").first_or_initialize do |user|
  # this won't run if a user with name "Roger" is found
  user.save 
end

User.find_or_initialize_by(name: "Roger") do |user|
  # this also won't run if a user with name "Roger" is found
  user.save
end

If you want to use a block regardless of the record's persistence, use tap on the result:

User.where(name: "Roger").first_or_initialize.tap do |user|
  user.email = "email@example.com"
  user.save
end

这篇关于Rails 创建或更新魔法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆