Мы хотели бы ввести триггер для установки значения в столбце в приложении на 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 по направляющим , но безрезультатно. Поиск в общей сети также провалился. Я искал "возвращение триггера rails activerecord", но ничего не было связано с тем, что мне нужно.
Можно ли заставить ActiveRecord читать больше записанной строки и перезагружать специфицированные c атрибуты?
Причина, по которой мы это делаем, состоит в том, чтобы избежать двойной записи на INSERT. Существующий код сохраняет, затем использует идентификатор записи для установки SKU в Ruby -land, а затем записывает столбец обратно в БД. Это означает 2 обхода БД для одной и той же операции. Столбец SKU также допускается NULL, что мне не очень нравится. Мы бы хотели сохранить туда-обратно в БД и установить NOT NULL
в столбце SKU. Если нам придется перезагрузить запись, это не позволит использовать триггер базы данных.