One problem with the
add_symbolic_names code posted earlier on the blog is the need to keep the test fixtures in sync with the data in the production database — otherwise, code can reference constants that exist in production, and will break while running tests.
Keeping these in sync is annoying enough that I wrote a rake task to dump the contents of a table to the appropriate fixtures file. I ended up with something like this:
desc "Overwrite a fixture file with the contents of a table (set by TABLE=)"
task :generate_from_table do
ActiveRecord::Base.establish_connection(RAILS_ENV)
table_name = ENV['TABLE']
File.open("test/fixtures/#{table_name}.yml", 'w') do |file|
data = ActiveRecord::Base.connection.select_all("SELECT * FROM #{table_name}")
rows = {}
data.each do |record|
rows["#{table_name}_#{record['id']}"] = record
end
file.write rows.to_yaml
end
end
Running this rake task will generate a fixture file containing all the information in the table specified by the environment variable
TABLE. In the future, we’ll probably look at automating the fixture generation for these symbolic tables so we don’t have to worry about failing tests when we add new rows.
UPDATE: I realized that in most cases, the symbolic name of the database row makes a much better fixture title than the id, which results in the following code:
desc "Overwrite a fixture file with the contents of a table (set by TABLE=)"
task :generate_from_table do
ActiveRecord::Base.establish_connection(RAILS_ENV)
table_name = ENV['TABLE']
File.open("test/fixtures/#{table_name}.yml", 'w') do |file|
data = ActiveRecord::Base.connection.select_all("SELECT * FROM #{table_name}")
rows = {}
data.each do |record|
fixture_name = record['symbolic_name'].blank? ?
"#{table_name}_#{record['id']}" :
record['symbolic_name'].downcase
rows[fixture_name] = record
end
file.write rows.to_yaml
end
end
This gives us nice fixtures that look like this:
---
dog:
name: Dog
id: "1"
symbolic_name: DOG
cat:
name: Cat
id: "2"
symbolic_name: CAT
No comments:
Post a Comment