Project

General

Profile

Actions

Patch #41954

open

Update extract_fixtures task with configurable output directory

Added by Ko Nagase 12 days ago. Updated 8 days ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
Code cleanup/refactoring
Target version:
-
Start date:
Due date:
% Done:

0%

Estimated time:

Description

I noticed that running extract_fixtures rake task failed with the following error.

% bundle exec rake extract_fixtures
rake aborted!
NoMethodError: undefined method `type_cast' for an instance of ActiveRecord::ConnectionAdapters::PostgreSQL::Column (NoMethodError)

          record[col.name] = col.type_cast(record[col.name]) if record[col.name]
                                ^^^^^^^^^^

Attached 1st patch (0001-Update-extract_fixtures-task-with-configurable-dir.patch) solves above issue with configurable output directory by DIR argument (envirionment variable, default ./tmp/fixtures), so reviewing it is helpful.

--- a/lib/tasks/extract_fixtures.rake
+++ b/lib/tasks/extract_fixtures.rake
@@ -19,17 +19,20 @@ desc 'Create YAML test fixtures from data in an existing database.
 Defaults to development database. Set RAILS_ENV to override.'

 task :extract_fixtures => :environment do
+  dir = ENV['DIR'] || './tmp/fixtures'
+  FileUtils.mkdir_p(dir)
+
   sql = "SELECT * FROM %s" 
-  skip_tables = ["schema_info"]
+  skip_tables = ["schema_migrations", "ar_internal_metadata"]
   ActiveRecord::Base.establish_connection
   (ActiveRecord::Base.connection.tables - skip_tables).each do |table_name|
     i = "000" 
-    File.open("#{Rails.root}/#{table_name}.yml", 'w' ) do |file|
+    File.open(File.join(dir, "#{table_name}.yml"), 'w') do |file|
       data = ActiveRecord::Base.connection.select_all(sql % table_name)
       file.write data.inject({}) { |hash, record|
         # cast extracted values
         ActiveRecord::Base.connection.columns(table_name).each { |col|
-          record[col.name] = col.type_cast(record[col.name]) if record[col.name]
+          record[col.name] = ActiveRecord::Type.lookup(col.type).deserialize(record[col.name]) if record[col.name]
         }
         hash["#{table_name}_#{i.succ!}"] = record
         hash

I tested mysql2, postgresql and sqlite3 adapters with attached test_extract_fixture.sh file on my local M1 Mac + Ruby 3.3.6 environment.

bash test_extract_fixture.sh mysql2
bash test_extract_fixture.sh postgresql
bash test_extract_fixture.sh sqlite3


Attached 2nd to 5th patches are for sort stability (2nd) and time offset/format things (3rd to 5th) and these are optional.


Files

Actions #1

Updated by Ko Nagase 8 days ago

Attached patches (6th to 8th) are also optional.
Full option example:

bundle exec rake extract_fixtures \
  DIR=./tmp/fixtures \
  TIME_OFFSET=+09:00 \
  SKIP_TABLES=import_items,imports \
  TABLE_FILTERS="issues:id IN (1,2);projects:id IN (1,2)" 

Restore example:
bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate
bundle exec rake db:fixtures:load FIXTURES_PATH=./tmp/fixtures

Actions

Also available in: Atom PDF