Reputation: 7702
How do I regenerate all the YML fixture files? I accidentally deleted them.
Upvotes: 8
Views: 1019
Reputation: 1199
When I use Nested Set in our app (let's say MyTree model here), lft/rgt columns calculation are required before use (during testing as well, of course). In order to set collect lft/rgt for all records in fixture of MyTree, there would be some approaches:
setup
block for every necessary test.a) above is quite tedious task for human. b) consumes CPU resource during test for each setup
. I think c) is the best approach so that I post my code here.
@sameera207 's code cannot be applied in our case because I use Label references for fixture entry, so that I write the following 'rake task' which generates test/fixtures/my_trees.yml
from test/fixtures.src/my_trees.yml
:
For example, data model is:
class MyTree < ApplicationRecord
acts_as_nested_set
...
end
and generating task is:
namespace :my_app do
desc 'rebuild from test/fixtures.src/my_trees.yml to test/fixtures/my_trees.yml'
task rebuild_my_trees_fixture: :environment do
require 'active_record/fixtures'
if !Rails.env.test?
puts('not test env')
next
end
id_to_entry = {} # ActiveRecord::FixtureSet#idnetity -> entry name
for key, val in YAML.load(ERB.new(File.read('test/fixtures.src/my_trees.yml'), 0, '-').result) do
id_to_entry[ActiveRecord::FixtureSet.identify(key)] = key
end
MyTree.transaction do
MyTree.delete_all
# load source to DB
::ActiveRecord::FixtureSet.create_fixtures('test/fixtures.src', 'my_trees')
MyTree.rebuild!(false)
File.open(Rails.root + 'test/fixtures/my_trees.yml', 'w') do |f|
# write header
f.write <<~EOS
# ===================================================================
# Do not modify this file manually!!
# This file is automatically generated.
# ===================================================================
EOS
hash = {}
for rec in MyTree.all do
key = id_to_entry[rec.id]
if key.nil?
STDERR.printf("ERROR: entry not found for id(%d)\n", rec.id)
else
hash[id_to_entry[rec.id]] = rec.attributes.except('id')
end
end
f.write(hash.to_yaml)
end
# cache should be cleaned here. Otherwise this working my_trees table
# remains at the 'rake test' later.
::ActiveRecord::FixtureSet.reset_cache
raise ActiveRecord::Rollback
end
end
end
# invoke above task before 'rake test'
task :'test' => 'my_app:rebuild_my_trees_fixture'
The key point is MyTree.rebuild!
in the above code, which calculates all of lft/rgt for all entries. All of other fragments of codes above are just preparation and generation.
I didn't have time to write this task to be invoked by file dependency trigger between fixtures.src/my_trees.yml
and test/fixtures/my_trees.yml
.
Upvotes: 0
Reputation: 16629
@brian,
I'm using the following script to generate the fixtures from a given sql
This is under my lib/task directory as a rake task
namespace :fixture_generator do
desc "generate fixtures for a given sql query from the current development database"
task :fixture_generator, [:sql, :file_name] => :environment do |t, args|
args.with_defaults(:sql => nil, :file_name => nil)
i = "000"
p "creating fixture - #{args.file_name}"
File.open("#{Rails.root}/test/fixtures/#{args.file_name}.yml", 'a+') do |file|
data = ActiveRecord::Base.connection.select_all(args.sql)
file.write data.inject({}) { |hash, record|
number = i.succ!
hash["#{args.file_name}_#{number}"] = record
hash
}.to_yaml
end
end
end
Usage, Say I want to generate fixture for users table
rake fixture_generator:fixture_generator["select * from users","users"]
And also, If you run another query with the same fixture file name, it will append to the existing one
HTH
Upvotes: 10