Lean Rails App Setup
I’m currently working as a consultant for an UN agency (IFAD) and we have a portfolio of ~15 Rails apps, developed in the last four years. The environment is heterogeneous and an half dozen of these projects are interfacing with legacy software and they are legacy themselves. As counterpart, the new apps we are developing are running on the latest bleeding edge technologies (Ruby 1.9.3, Rails 3.2, MongoDB, Redis, WebSockets etc..).
When I joined the team in last September, I had big problems to deal with all this amount of informations and to clone projects from GitHub then make them running on my dev machine. The most common issue is the missing and/or outdated documentation. Developers are lazy people and, in general, they just want to code. Documentation, UI/UX reviews are just an example of what they tend to avoid.
The post-git-clone syndrome became really frustrating for each project I needed to work on, so now I aim to document and create a single Rake task for setup.
Since we have several persistence options, to run all these databases as init.d services would be overkilling for my MacBook. So I went for the all-turned-off-by-default strategy and run only the processes that I actually need for a code session. I’m a big fan of Foreman, and it perfectly fits this need. Plus I don’t have to remind which is the database(s) needed for that specific project or if it needs a queue, everything is ready with just foreman start.
In our team we almost all use Mac (with Homebrew) as setup, but since a Foreman’s Procfile is too much coupled with the current machine is running on, I create a Procfile.example in each project and let my colleagues to customize their own configuration, according their machine, or completely skip it and use their own workflow. Remember, the goal isn’t about unify the development process, but to have the application running in less than 5 minutes, for people who never worked on that project before.
Here a complete and working example:
# lib/tasks/app.rake
namespace :app do
desc 'Setup the application'
task :setup do
require 'fileutils'
# ENVIRONMENT
puts "\n** Configuring servers.\n"
## Foreman
puts "*** Configuring Foreman."
FileUtils.cp Rails.root.join('Procfile.example'),
Rails.root.join('Procfile')
## Pow
puts "*** Configuring Pow."
FileUtils.ln_sf Rails.root, File.expand_path('~/.pow')
FileUtils.touch Rails.root.join('tmp/always_restart.txt')
# DATABASE
## Postgres
puts "\n** Configuring database.\n"
puts "*** Configuring Postgres: your current UNIX username is being used for connection."
FileUtils.cp Rails.root.join('config', 'database.yml.example'),
Rails.root.join('config', 'database.yml')
## Setup
puts "*** Setting up the database."
pids = %w( db ).map do |process|
Kernel.spawn("foreman start #{process}")
end
sleep 4
Thread.new do
begin
Rake::Task['db:setup'].invoke
rescue Exception => e
puts "*** [ ERROR ] failed to load the database: #{e.message}"
end
end.join
pids.each do |pid|
Process.kill('SIGTERM', pid)
end
end
end