Как сделать триггер обратимым в миграции рельсов - PullRequest
0 голосов
/ 26 сентября 2019

Я пишу миграцию в Ruby on Rails, которая содержит триггеры, и при откате я получил следующую ошибку:

ActiveRecord::IrreversibleMigration: 

This migration uses execute, which is not automatically reversible.
To make the migration reversible you can either:
1. Define #up and #down methods in place of the #change method.
2. Use the #reversible method to define reversible behavior.

Я определил все таблицы и триггеры в функции изменения:

class Geolocation < ActiveRecord::Migration[5.0]
    def change
     [...]
     execute <<-SQL
        CREATE OR REPLACE FUNCTION zone_preset_jolly_city() RETURNS trigger
        LANGUAGE plpgsql AS 
        $$BEGIN
          INSERT INTO cities( zone_preset_id, name ) VALUES ( NEW.zone_id, '%' );
          RETURN NEW;
        END;$$;

        CREATE OR REPLACE FUNCTION city_jolly_toponym() RETURNS trigger
        LANGUAGE plpgsql AS 
        $$BEGIN
          INSERT INTO toponyms( city_id, toponym_type_id, name ) VALUES ( NEW.city_id, '%', '%' );
          RETURN NEW;
        END;$$;

        CREATE OR REPLACE FUNCTION toponym_jolly_street_number() RETURNS trigger
        LANGUAGE plpgsql AS 
        $$BEGIN
          INSERT INTO street_numbers( toponym_id, number ) VALUES ( NEW.toponym_id, '%' );
          RETURN NEW;
        END;$$; 

        CREATE TRIGGER zone_preset_jolly
          AFTER INSERT ON zone_presets
          FOR EACH ROW EXECUTE PROCEDURE zone_preset_jolly_city();

        CREATE TRIGGER city_jolly_toponym
          AFTER INSERT ON cities
          FOR EACH ROW EXECUTE PROCEDURE city_jolly_toponym();

        CREATE TRIGGER toponym_jolly_street_number
          AFTER INSERT ON toponyms
          FOR EACH ROW EXECUTE PROCEDURE toponym_jolly_street_number();
      SQL
end

Итак, я пытаюсь определить функцию «вверх» и «вниз», чтобы правильно отменить триггеры, но я не знаю, как определить их обратное.Есть предложения?

Ответы [ 3 ]

1 голос
/ 26 сентября 2019

Если вас не волнует изменение данных в обратимой миграции, просто переименуйте метод изменения в up и создайте пустой метод down:

class Geolocation < ActiveRecord::Migration[5.0]

  # this used to be def change
  def up
    ...
    ...
  ...
  end

  def down
  end
end

Если вам не все равносделав его обратимым, вам нужно будет инвертировать все транзакции, которые вы выполняете в методе up, и запускать их в своем методе down.Но, конечно, не все будет полностью обратимо.

0 голосов
/ 27 сентября 2019

Спасибо за все ваши ответы!Я исправил это и вот полный пример для других людей, которым это нужно:

def change
[...]

 reversible do |dir|
   dir.up do
     execute <<-SQL
       CREATE OR REPLACE FUNCTION zone_preset_jolly_city() RETURNS trigger
       LANGUAGE plpgsql AS 
       $$BEGIN
         INSERT INTO cities( zone_preset_id, name ) VALUES ( NEW.zone_id, '%' );
         RETURN NEW;
       END;$$;

       CREATE OR REPLACE FUNCTION city_jolly_toponym() RETURNS trigger
       LANGUAGE plpgsql AS 
       $$BEGIN
         INSERT INTO toponyms( city_id, toponym_type_id, name ) VALUES ( NEW.city_id, '%', '%' );
         RETURN NEW;
       END;$$;

       CREATE OR REPLACE FUNCTION toponym_jolly_street_number() RETURNS trigger
       LANGUAGE plpgsql AS 
       $$BEGIN
         INSERT INTO street_numbers( toponym_id, number ) VALUES ( NEW.toponym_id, '%' );
         RETURN NEW;
       END;$$; 

       CREATE TRIGGER zone_preset_jolly
         AFTER INSERT ON zone_presets
         FOR EACH ROW EXECUTE PROCEDURE zone_preset_jolly_city();

       CREATE TRIGGER city_jolly_toponym
         AFTER INSERT ON cities
         FOR EACH ROW EXECUTE PROCEDURE city_jolly_toponym();

       CREATE TRIGGER toponym_jolly_street_number
         AFTER INSERT ON toponyms
         FOR EACH ROW EXECUTE PROCEDURE toponym_jolly_street_number();
     SQL
   end

   dir.down do
     execute <<-SQL
       DROP TRIGGER toponym_jolly_street_number ON toponyms;
       DROP TRIGGER city_jolly_toponym ON cities;
       DROP TRIGGER zone_preset_jolly ON zone_presets;
     SQL
   end
 end
end
0 голосов
/ 26 сентября 2019

Мне нравится использовать обратимый в этих случаях.

class MigrationName < ActiveRecord::Migration[5.2]
  def change
    reversible do |dir|
      dir.up do
        execute <<-SQL
          INSERT INTO users VALUES ('name');
        SQL
      end

      dir.down do
        execute <<-SQL
          DELETE FROM users;
        SQL
      end
    end
  end
end

...