ruby-on-rails - 在保存块内保存属性的最佳方法?
问题描述
在我的控制器中,我经常有这样的功能:
@account = Account.new(account_params)
if @account.save
if @account.guest?
...
else
AccountMailer.activation(@account).deliver_later
@account.update_column(:activation_sent_at, Time.zone.now)
flash[:success] = "We've sent you an email."
redirect_to root_path
end
end
发送电子邮件和更新activation_sent_at
属性而无需保存记录两次的最佳方式是什么?在这里调用update_column
对我来说感觉不对,因为 AFAIK 它会创建一个额外的 SQL 查询(如果我错了,请纠正我)。
解决方案
你的代码很好。我不会改变它。
例如,您可能很想做这样的事情:
@account = Account.new(account_params)
@account.activation_sent_at = Time.zone.now unless @account.guest?
if @account.save
if @account.guest?
...
else
AccountMailer.activation(@account).deliver_later
flash[:success] = "We've sent you an email."
redirect_to root_path
end
end
除了现在重复逻辑的小问题,@account.guest?
如果失败会发生AccountMailer.activation(@account).deliver_later
什么?(当我说“失败”时,我的意思是 - 例如 -AccountMailer
已重命名,因此控制器返回 500 错误。)
在这种情况下,您最终会得到一堆account
记录,这些记录有activation_sent_at
但从未发送过电子邮件;而且你没有简单的方法来区分它们。
因此,这段代码保证运行两个数据库调用:一个用于创建记录,另一个用于确认电子邮件已发送。如果您将代码重构为仅执行一次数据库调用,那么您将容易受到以下任何一种情况的影响:
- 向非创建用户发送电子邮件,或
activation_sent_at
尽管发送了电子邮件,但仍用标记用户。
控制器应该做两个事务,而不是一个。这就是为什么我说:不要改变它。
推荐阅读
- python - Python pandas 将两个数据帧中的列相乘以获得每行(组)的数字
- c# - Visual Studio 2019 未创建 OBJ 或 BIN 文件夹
- css - React Div 滚动绑定另一个 Div
- google-apps-script - Google 电子表格范围的屏幕截图
- three.js - 有没有办法修复类型'null'不能用作索引类型.ts(2538)
- c - 如何防止线程读取 DPDK RX 和 TX 缓冲区?
- swift - 捐赠快捷方式时的问题:无法捐赠与没有有效快捷方式类型的意图的交互
- transactions - 是否可以原子地向rabbitMQ发布两条消息?
- reactjs - html-react-parser:将 DOM 节点替换为另一个包含内部文本子节点的 DOM 节点(A-link)
- python - url_for() 不渲染子目录中的文件