ruby-on-rails - 如何在 Rails ActiveRecord 中返回生成的列?
问题描述
我们想在 Rails 6 应用程序中引入一个触发器来设置列的值。该表如下所示(PostgreSQL 9.6):
CREATE TABLE foo(
id bigserial primary key
, sku text not null unique
-- ...
);
在创建时,我们的代码在 SKU 上设置了一个前缀:
class Foo < ApplicationRecord
before_create :set_sku_prefix
private
def set_sku_prefix
self[:sku] = "AAA-"
end
end
当触发器触发时,它会完成记录设置:
CREATE OR REPLACE FUNCTION generate_sku() RETURNS trigger AS $$
BEGIN
-- Simplified, real trigger handles ID already being set,
-- and other edge cases related to the length of the returned value.
NEW.id = nextval('public.foos_id_seq');
NEW.sku = NEW.sku || RIGHT('000000', NEW.id, 6);
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER generate_sku
BEFORE INSERT OR UPDATE
ON foos
FOR EACH ROW
WHEN (RIGHT(NEW.sku, 1) = '-')
EXECUTE PROCEDURE generate_sku();
当 ActiveRecord 生成 SQL 语句来执行插入时,它会这样做:
INSERT INTO foos(sku) VALUES ('AAA-') RETURNING id
我想更改最后一条语句,使其也返回 SKU,并让 ActiveRecord 将内存中的属性值更新为数据库生成的值:
INSERT INTO foos(sku) VALUES ('AAA-') RETURNING id, sku
最后,我希望以下内容属实:
foo = Foo.create!
if foo.sku == ("AAA-%06d" % [foo.id])
puts "All good!"
else
puts "Oops, wrong"
end
我已经阅读了大部分ActiveRecord API 文档和Ruby on Rails 指南,但无济于事。在一般网络上搜索也失败了。我搜索了“rails activerecord 触发器返回”,没有任何与我需要的东西真正相关的内容。
是否可以让 ActiveRecord 读取更多写入的行并重新加载特定属性?
我们这样做的原因是为了避免在 INSERT 上重复写入。现有代码保存,然后使用记录的 ID 在 Ruby-land 中设置 SKU,然后将列写回数据库。这意味着同一操作需要 2 次 DB 往返。SKU 列也允许为 NULL,我不太喜欢。我们想保存到数据库的往返,并NOT NULL
在 SKU 列上强制执行。如果我们必须重新加载记录,这将破坏使用数据库触发器的目的。
解决方案
推荐阅读
- mysql - 如何发现 MariaDB 崩溃的原因?
- r - 是否可以从闪亮服务器上的传单地图 R 关闭/打开图例或覆盖组/图例?
- arkit - Reality Composer USDZ 动画与其他动画
- python - Python - pyinstaller - pyinstaller 的可执行项目有错误无法执行脚本 pyi_rth_pkges
- ios - SwiftUI 更改和动画前景色
- python - 如何通过不同长度的列表生成随机句子?
- java - 将 https:IP 地址重定向到 https:localhost
- ssl - cert-manager Ingress Controller 找不到证书
- c - 无法将文件中的数据读入链表
- arrays - Laravel 集合图的方法来展平多维