DEV Community

Cover image for Rails Tasks: exporting database models to a CSV.
Richard MacCaw
Richard MacCaw

Posted on

Rails Tasks: exporting database models to a CSV.

If you just want the code, scroll to the bottom πŸ₯³

Rails has some really nice ways to make a developers life a bit easier. One of them is Rake Tasks. If you have ever executed the command rails c, or rake db:migrate, you've already used tasks. Since version 5.0, Rails allows you to call most rake commands with rails instead.

A bit of background

We needed an automated and simple way to share our database design across the company. A schema file didn't cut it.

ERD gem is a great option to share the high level overview. We use it all the time. It generates a nice PDF showing model associations and attributes (tutorial to come shortly).

But for the nitty gritty details we made a task which exports our database models, attributes and data types to a CSV.


Let's break it down.

  • Create a models_to_csv.rake file over in lib/tasks.
  • require 'csv' (built into Rails) to be able to generate CSV's.
  • Define your task name and list under an optional namespace.
# lib/tasks/models_to_csv.rake

require 'csv'

namespace :custom do
  desc 'Generate a CSV with all models, attribute names, and attribute database types'

  task models_to_csv: :environment do
  end

end
  • Load all your database models into memory. Rails does not eager_load by default in Rake Tasks. Note for Rails 5 and below, you should do Rails.application.eager_load!
  • Define where you want to save the CSV.
  • Set the column names you want. Three names equals three columns.
  • Open up the CSV block and pass in the headers.
# lib/tasks/models_to_csv.rake

require 'csv'

namespace :custom do
  desc 'Generate a CSV with all models, attribute names, and attribute database types'

  task models_to_csv: :environment do

    Zeitwerk::Loader.eager_load_all
    file = Rails.root.join('public/model_data.csv')
    headers = %w[Model Attribute Type].freeze

    CSV.open(file, 'w', write_headers: true, headers: headers) do |writer|
    end
  end
end

Right! Thats the set up done. Next we need to loop through all our model attributes and generate the CSV.

  • Iterate over ActiveRecord::Base.descendants to get your models.
  • Skip any models you don't want.
  • Iterate over each models attributes.
  • Add the model name, attribute and attribute data type to the CSV writer.
  • Profit πŸ’Έ
# lib/tasks/models_to_csv.rake

require 'csv'

namespace :custom do
  desc 'Generate a CSV with all models, attribute names, and attribute database types'

  task models_to_csv: :environment do

    Zeitwerk::Loader.eager_load_all
    file = Rails.root.join('public/model_data.csv')
    headers = %w[Model Attribute Type].freeze

    CSV.open(file, 'w', write_headers: true, headers: headers) do |writer|
      ActiveRecord::Base.descendants.each do |model|
        next if model.name.starts_with?('ActiveStorage')

        model.attribute_names.each do |attribute|
          writer << [model.name, attribute, model.columns_hash[attribute].type.to_s]
        end
      end
    end
    puts 'CSV generated here -> /public/model_data.csv'
  end
end

Awesome. Now all we need to do is run our new task.

rails custom:models_to_csv


PS. We are looking for great Product Engineers over at Generation Home. We are a funded, UK based, pre-launch tech company, tying to create more ways into home ownership. 🏠

Top comments (0)