Rails Fixtures load order
This was a head breaking experience for me recently.
We all know that the fixtures files in rails load by default in alphabetical order. And the records inside every single file again load in alphabetical order (not from top to bottom as you define in the fixture file). Considering that having database level constraints (foreign keys, primary keys etc) is advisable idea in spite of having the rails model level relations (belongs_to, has_many etc), loading fixtures in alphabetical order is the most stupid thing I can ever think of. Imagine you have Account and Employee models and employee has_many accounts. So you have an employee_id sitting as a foreign key in the accounts table. Now you want to load your fixtures (rake db:fixtures:load), for test purpose say, which was my requirement. Since ‘A’ comes before ‘E’ in alphabetical order, rails tries to load the addresses first and then the employees fixture file. Obviously this fails because of foreign key violations. Database raising errors is perfectly making sense here. So I looked around for something which may solve this problem and found that there are solutions available given by some people. But what surprised me is that there is nothing that rails core provided for this.
Anyways, so for people who are into this kinda problem, here is the best one called ActiveFixture that I came across and wish that it would get included in the rails core someday.
Again there is something that may surprise you again. Its not that rails has been stupid all these days to leave us in such a situation. It might so happen that you may not do anything for ordering of the fixtures and still would not get any error although you have foreign key relationships in the database. The reason actually lies in the active record’s database (postgres, mysql sql-lite etc) adapters class. Here is how it goes. While loading the fixtures (I am giving postgres example, as I am using postgres for this project and found it there), rails calls the following method in ActiveRecord::ConnectionAdapters::PostgreSQLAdapter:
def supports_disable_referential_integrity?() #:nodoc:
version = query("SHOW server_version").split('.')
(version.to_i >= 8 && version.to_i >= 1) ? true : false
So this method says, that if you pgsql version is x.y.z, then if x >= 8 and y >= 1, then it will be able to defer the referential integrity for you and you could load the data from fixtures into your database easily without taking care of the ordering and without facing any data integrity errors 😀 Unfortunately I, in my team, was using 9.y.z version of pgsql and all my collegues were on 8.1.4. So they were not getting any errors and I was frustated to know WHY.
Well the secret lies in the ConnectionAdapters for rails 😀 I don’t know if we should take it as an advantage, that rails is trying to do or not, but until we have something more intelligent to infer the order of loading the fixtures files from the relationships in the models, rather than defining the load order manually as mentioned here, I am happy that its saving me some time.