Rails,PostgreSQL和历史触发器

所以…

我正在通过类似的东西添加由触发器填充的历史表,以便在我的项目中进行审计。

execute <<-SQL CREATE OR REPLACE FUNCTION process_history_table() RETURNS TRIGGER AS $history_table$ BEGIN IF (TG_OP = 'DELETE') THEN INSERT INTO history_table VALUES (DEFAULT, 'D', now(), OLD.*); RETURN OLD; ELSIF (TG_OP = 'UPDATE') THEN INSERT INTO history_table VALUES (DEFAULT, 'U', now(), NEW.*); RETURN NEW; ELSIF (TG_OP = 'INSERT') THEN INSERT INTO history_table VALUES (DEFAULT, 'I', now(), NEW.*); RETURN NEW; END IF; RETURN NULL; -- result is ignored since this is an AFTER trigger END; $history_table$ LANGUAGE plpgsql; CREATE TRIGGER history_table AFTER INSERT OR UPDATE OR DELETE ON table FOR EACH ROW EXECUTE PROCEDURE process_history_table(); SQL 

……这将适用于生产和其他环境。 问题是当有人运行bundle exec rake db:drop db:create db:schema:load db:migrate RAILS_ENV=test或类似的东西(最重要的是db:schema:load部分),这将绕过触发器创建,因为触发器是未保存在db/schema.rb文件中。

也许正确的解决方案是,在使用rails时,开发人员不应该运行db:schema:load并始终运行db:migrate以确保可以连续重新运行所有迁移。 但是,我们很长一段时间没有采用这种方式运行,我认为这样做会非常痛苦,因为我们可能需要更新几十个或更多的迁移。 关于如何将触发器逐步合并到我的应用程序中以及继续以与今天相同的方式构建/重新创建开发人员/测试环境的任何想法将非常有帮助。

谢谢!

如果您需要或想要ActiveRecord不理解的特定于数据库的function,那么您应该切换到db/structure.sql以跟踪您的架构。 db/structure.sql几乎是使用数据库的本机工具制作的模式的原始转储,因此它将包含触发器,CHECK约束,函数结果索引以及其他所有内容。

切换很简单:

  1. 更新config/application.rb以包含config.active_record.schema_format = :sql
  2. 执行rake db:structure:dump以获取初始db/structure.sql
  3. 从目录树和版本控制中删除db/schema.rb
  4. db/structure.sql添加到版本控制。
  5. 调整你的佣金习惯:
    • 使用db:structure:dump而不是db:schema:dump
    • 使用db:structure:load而不是db:schema:load

其他一切都应该像往常一样工作(当然,假设你是理智的,并使用PostgreSQL进行开发,测试和生产)。

通过此更改,将在db/structure.sql跟踪您的触发器,并重新创建数据库不会丢失它们。

您可以使用gem 'paper_trail'跟踪更改模型,进行审核或版本控制。 链接在这里

不是https://github.com/jenseng/hair_trigger你需要什么?

它允许您在项目中注册触发器,然后重新创建,使用命令更新它们。

注意:我一直想使用它,但由于各种原因最终没有机会完成它,所以我不能保证gem的质量。

编辑:不,他们应该总是使用rake db:schema:加载现有的数据库