How do I work with tests and fixtures on a database that contains foreign key constraints in Rails?

4

I am using RubyOnRails 4.1 and PostgreSQL database and I use gem foreigner to create foreign key constraints in the bank. It turns out that this makes some tasks difficult with fixtures .

When I try to run a test:

spring rake test

I often have errors like this:

ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR:  update or delete on table "TABELA1" violates foreign key constraint "TABELA2_TABELA1_id_fk" on table "TABELA2"
DETAIL:  Key (id)=(980190962) is still referenced from table "TABELA2".
: DELETE FROM "TABELA1"

I can only run my tests because it recreates the database before running them:

RAILS_ENV=test spring rake db:reset && spring rake test

I also can not use rake db:fixture:load to upar fixtures for the development bank, it gives the same error.

Changing the order of fixtures in the file test_helper.rb was not enough.

Does anyone know how I can solve this? I did a lot of research on web and did not find a solution.

    
asked by anonymous 21.08.2014 / 13:43

3 answers

1

One possible workaround is: instead of fixtures, work with factory_girl . And to clean the database between tests, the Database Cleaner .

    
22.08.2014 / 19:00
1

See the error:

  

ForeignKeyViolation: ERROR: update or delete on table "TABLE1" violates foreign key constraint "TABLE2_TABELA1_id_fk" on table "TABLE2"   DETAIL: Key (id) = (980190962) is still referenced from table "TABLE2".

You can not delete a record from table 1 without first removing the reference from table 2. Then in this case delete all references before deleting the record.

In addition, see the documentation for PostgreSQL .

You could create the reference with ON DELETE CASCADE . Therefore, by deleting the record from table 1 the references from table 2 would be automatically deleted. There are other options that might be interesting in your case as:

  • RESTRICT
  • NO ACTION
  • CASCADE
  • SET NULL
  • SET DEFAULT
01.11.2014 / 15:39
1

I was the original author of the question, and finally I was able to solve this problem definitively.

The truth is that Rails attempts to disable triggers that checks the foreign key references before the setup of running the tests, when the base is cleaned, in> fixtures are reinserted in the base. After the setup , but before the tests are run, the triggers are re-enabled.

It turns out that, for security reasons, Postgres only allows superuser users to disable these triggers . (Do not confuse the Linux superuser with Postgres superuser, they're two different things!) If you are logged in as a "regular" user, triggers will remain enabled and setup will fail.

Solution

So the solution is relatively simple. Just make your user a superuser in Postgres:

ALTER ROLE meuusuario SUPERUSER;

And automagically everything will work as it should.

    
07.11.2014 / 17:13