在我的 Rails 3.1.3 应用程序中,我有 subscriptions
表;必须跟踪该表上的操作,这对于计费至关重要。由于可以通过多种方式访问数据库(API、控制台、客户端应用程序),因此简单的 ActiveRecord 回调或观察器不足以确保记录表上的所有事务。因此,我在 subscriptions
表上创建一个数据库触发器,只要发生变化,它就会在“log”表中插入一条记录。为了做到这一点,我使用 Rails 迁移,如下所示:
def up
execute <<-SQL
CREATE OR REPLACE FUNCTION FUNCTION_Event_Type()
RETURNS TRIGGER
AS
$TRIGGER_Event_Type$
BEGIN
IF (TG_OP = 'DELETE') THEN
INSERT INTO subscription_log (company_id, product_id, old_package_id, new_package_id, trigger_type, updated_at, created_at)
SELECT OLD.company_id, OLD.product_id, OLD.package_id, NULL, 'Delete', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO subscription_log (company_id, product_id, old_package_id, new_package_id, trigger_type, updated_at, created_at)
SELECT OLD.company_id, OLD.product_id, OLD.package_id, NEW.package_id, 'Update', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP;
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO subscription_log (company_id, product_id, old_package_id, new_package_id, trigger_type, updated_at, created_at)
SELECT NEW.company_id, NEW.product_id, NULL, NEW.package_id, 'Insert', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP;
RETURN NEW;
END IF;
RETURN NULL;
END;
$TRIGGER_Event_Type$
LANGUAGE plpgsql;
CREATE TRIGGER TRIGGER_Event_Type
AFTER INSERT OR UPDATE OR DELETE ON subscriptions
FOR EACH ROW EXECUTE PROCEDURE FUNCTION_Event_Type();
SQL
end
触发器工作正常并根据需要记录。我有 rspec 测试,检查每当在 subscriptions
表上完成某些操作时,记录都会插入到“logging”表中。但是,我继续开发该应用程序,并且必须使用 Rails 迁移向 subscriptions
表添加一列:
def change
add_column :subscriptions, :description, :text
end
运行迁移后,我的测试会检查触发器功能,如下所示:
lambda do
FactoryGirl.create(:subscription)
end.should change(SubscriptionLog, :count).by(1)
开始失败。
更新:开发数据库在添加列后仍然有触发器。运行添加列的迁移后,测试数据库丢失触发器...奇怪
问题:
更改表会杀死触发器吗?如果确实如此,如何确保触发器持续存在?
最佳答案
我终于明白了。向 subscriptions
表添加一列后,我运行了 rake db:test:prepare
(不要问我为什么)。显然,“转储当前模式,清除测试数据库,然后从转储中重建测试模式”由于触发器是通过执行 SQL(而不是 Rails 帮助程序)创建的,因此它从未反射(reflect)在模式文件中。因此,它从未被 rake db:test:prepare 重新创建 解决方案:删除测试数据库并再次运行所有迁移...并且永远不要运行 rake db:test:prepare > 再次。希望有人觉得它有用。
关于ruby-on-rails - 在 Rails 应用程序中更改 PostgreSQL 表会禁用触发器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10335263/