# frozen_string_literal: false namespace :db do # Usage example: # RAILS_ENV=test rails db:to_fixtures[chained_elements] desc 'Convert development DB to Rails test fixtures' task :to_fixtures, [:table] => :environment do |_task, args| tables_to_skip = %w[ar_internal_metadata delayed_jobs schema_info schema_migrations].freeze begin ActiveRecord::Base.establish_connection ActiveRecord::Base.connection.tables.each do |table_name| next if tables_to_skip.include?(table_name) next if args.table && args.table != table_name counter = '000' file_path = Rails.root.join("test/fixtures/#{table_name}.yml") File.open(file_path, File::WRONLY | File::CREAT) do |file| rows = ActiveRecord::Base.connection.select_all("SELECT * FROM #{table_name}") data = rows.each_with_object({}) do |record, hash| suffix = record['id'].presence || counter.succ! # FIXME, this is broken with jsonb columns: it records a String but a Hash must be saved hash["#{table_name.singularize}#{suffix}"] = yamlize(record, rows.column_types) end puts "Writing table '#{table_name}' to '#{file_path}'" file.write(data.to_yaml) end end ensure ActiveRecord::Base.connection&.close end end def yamlize(record, column_types) record.each_with_object({}) do |(key, value), hash| hash[key] = column_types.include?(key) && column_types[key].type == :jsonb ? JSON.parse(value) : value end end end