2015-01-20 11 views
16

Gibt es eine Möglichkeit, Rails-Vorrichtungen in einer bestimmten Reihenfolge zu laden, während Tests ausgeführt werden? Nehmen wir zum Beispiel die folgenden Klassen ...Laden von Schienenvorrichtungen in einer bestimmten Reihenfolge beim Testen

class User < ActiveRecord::Base 
    has_many :memberships 
    has_many :groups, through: :memberships 
end 

class Group < ActiveRecord::Base 
    has_many :memberships 
    has_many :users, through: :memberships 
end 

class Membership < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :group 
end 

Memberships haben eine Datenbankebene Fremdschlüssel Users und Groups erfordern vorhanden sein, bevor sie erstellt werden können. Da jedoch Rails das Gerät alphabetisch lädt, werden Memberships vor Users geladen, und ein Fehler tritt auf, der besagt, dass die Beziehungen nicht existieren (zu Recht).

ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "memberships" violates foreign key constraint 

Gibt es eine Möglichkeit, die Users und Groups Vorrichtungen zu laden, bevor Memberships Laden während Tests ausgeführt werden?

+0

Verwenden Sie benannte Fixtures? Siehe hier: http://stackoverflow.com/questions/510195/rails-fixtures-how-do-you-set-foreign-keys – davidfurber

+0

Ja, ich verwende benannte Fixtures. –

+0

Haben Sie versucht, die FIXTURES env var einzustellen? Und/oder den "Fixtures" -Befehl im Test verwenden, um anzugeben, welche Fixtures geladen werden sollen? – davidfurber

Antwort

36

Ihr Problem ist nicht die Reihenfolge, in der Rails Ihre Tests ausführt. Ich hatte das gleiche Problem wie Sie, und nach dem Debuggen für ein paar Stunden festgestellt, dass ActiveRecord tatsächlich referenzielle Integrität beim Einfügen von Fixture-Datensätze deaktivieren diese Art von Fehlern für Postgresql zu deaktivieren.

Der Haken ist, dass Ihr Testdatenbankbenutzer über Superuser-Berechtigungen für die Test-Db verfügen muss, damit ActiveRecord die referenzielle Integrität für Fixtures erfolgreich deaktiviert.

Hier ist, wie Sie Ihr Problem zu beheben:

  1. Log in Postgresql mit Ihrem Standard-Super-User (bei mir ist "Postgres")
  2. Führen Sie den folgenden Befehl ein:

    ALTER ROLE yourtestdbuser WITH SUPERUSER; 
    
  3. Genießen Sie Ihren richtig funktionierende Armaturen.

Die nächste Version von Rails wird eine Warnung (was ich denke, ist dringend erforderlich), wenn eine Person ohne Superuser-Rolle eine Testdatenbank mit Postgresql und einem Benutzer ausgeführt wird. Ich habe das auf a Rails GitHub issue suggesting the warning gefunden.

+1

Funktioniert perfekt. Vielen Dank! –

+0

Ich stoße auf dieses Problem in einer RDS Postgres-Instanz. Gibt es etwas Besonderes, das RDS in den Mix werfen würde? Ist die von RDS bereitgestellte "Superuser" -Rolle die gleiche wie bei einem normalen Superuser? – sixty4bit

+0

Ich sollte auch hinzufügen, dass meine Rails scheint nicht zu laden Fixtures in alphabetischer Reihenfolge, wie VanguardFunds geladen wird (die auf BenchmarkFunds beruht) vor BenchmarkFunds – sixty4bit

9

Durch die Vergabe von PostgreSQL-Superuser-Privilegien an Ihr "Test" -Konto kann Rails so arbeiten, wie es arbeiten möchte. In Fällen, in denen dies nicht/machbar gewünscht ...

Ja, ist es möglich, - wenn nicht unterstützt - zur Steuerung der Reihenfolge, in der Vorrichtungen geladen werden und gelöscht (beide sind wichtig) .

In test/test_helper.rb:

class ActiveRecord::FixtureSet 
    class << self 
    alias :orig_create_fixtures :create_fixtures 
    end 
    def self.create_fixtures f_dir, fs_names, *args 
    # Delete all fixtures that have foreign keys, in an order that 
    # doesn't break referential integrity. 
    Membership.delete_all 

    reset_cache 

    # If we're adding any {user, group} fixtures, add them [a] in that 
    # order, [b] before adding any other fixtures which might have 
    # references to them. 
    fs_names = %w(users groups) & fs_names | fs_names 

    orig_create_fixtures f_dir, fs_names, *args 
    end 
end 

Getestet mit Rails 4.2.3, und nur dann, wenn fixtures :all verwenden.

+0

Dies behebt das Problem für mich (Ich bin nicht in der Lage, Änderungen an DB-Benutzer in RDS aus irgendeinem Grund). Ich danke dir sehr! – sixty4bit

+0

rettete mein Leben Mann! Getestet mit JDBC- und Informix-Verbindung. Vielen Dank! –

Verwandte Themen