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 inlib/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 doRails.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)