Thursday, 6 June 2013

Rails: TDD Workflow

I try to keep things simple. This is my personal workflow as a single developer. This workflow evolves continually as I grow as a developer and as new tools and practices becomes available. These are my tools: Ruby, Rails, Rspec, Capybara, Git

This is an overview: For production apps I have a development, staging and production environment. As a start to a cycle I only have a master branch. I create a new branch for every feature (named after the feature) and when ready (all tests green) I create the development branch from the feature branch. The development branch pushes to the staging environment. When all tests green on staging I merge with master branch, push to production and delete the feature and development branches.

Here are more detailed steps:

  1. I write out a story for a feature with sketches.
  2. I create a new branch(I try to not code in master branch)
    git checkout -b newfeaturename
  3. I write my Rspec tests to test the feature
  4. I use Spork to pre-load my rails environment (run spork from the console) and a focus tag in the test to only run my new tests.

    In rspec test

    it "can email advertisers with no listings", focus: true do

    Then in console run:

    rspec spec --drb --tag focus

    The --drb option above make use of the spork service allready running

  5. Implement the code to make tests pass.
  6. After each test is green or refactored commit to version control

    git add .

    git commit -am "My commit message"

  7. When all tests are green and the feature is implemented I create the development branch
    git checkout -b development
  8. Push to staging:(I use Heroku)
    git push staging development:master
  9. Do integration tests against staging with saucelabs and a seed database
  10. If all good, merge with master

    git checkout master

    git merge development

  11. Push to git repositry (I use Bitbucket)
    git push bitbucket master
  12. Push to production (I use Heroku)
    git push heroku master
  13. Rinse and repeat with new features

Monday, 3 June 2013

Rails: Custom Rake Tasks

Rake is a great command line utility for rails. Most rails developers will use it for database migrations.

rake db:migrate

You can also see what rake tasks is available to you by running the following command from the command line.

rake -T

This post is about creating custom rake tasks that you can view with the above command and run to do tasks for your rails application that you would not want to do from within the application because it would take too long.

We start with a simple example by creating a file with a demo.rake extension in the lib/tasks/ folder of your rails app with the following code.

task :hello_world do
  puts 'Hello World!'
end
Now run the command from the command line.
rake hello_world

It should have printed out your puts command. If you run rake -T you will find that it does not list your new task. To do that you have to add a description to your task so that it looks like this.

desc "Prints Hello World!"
task :hello_world do
  puts 'Hello World!'
end

It will now be in the list when you run rake -T. You saw that a rake task is called by its task name and not file name. You can have multiple tasks in the same rake file with its own desc and task block. You don't wrap the whole file in a block.

I personally use custom rake commands to do db maintenance while offline or to run scripts that collects information from the internet and saves it to database. To have a rake task interact with your rails app you have to load the rails environment and you do that by loading it is a dependency. You add => environment after you task name. Here is an example rake file that resets all the products or users in your db. This saves you having to drop into rails console to methods on models.

desc "Deletes all products in db"
task :reset_products => :environment do
  Product.destroy_all
end

desc "Deletes all users in db"
task :reset_users => :environment do
  User.destroy_all
end

I use this mainly on my development machine while rails server is not running. Some of my tasks do scraping jobs and can take hours to run. If you ran that from within the app your app would have been frozen waiting for the job to finish. Also be careful to run a rake task that saves to the database while the app is running as it can lock the db (when using webrick).