Как вернуть сгенерированные столбцы в Rails ActiveRecord? - PullRequest
2 голосов
/ 26 марта 2020

Мы хотели бы ввести триггер для установки значения в столбце в приложении на 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. Если нам придется перезагрузить запись, это не позволит использовать триггер базы данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...