codedecoder

breaking into the unknown…

custom rake task in rails

2 Comments

rake command is explained in this post. rails provide a number of inbuilt tasks, but you can create your own task also as explained here.

=> Understanding the basics :

When you create any new rails project(example: rails new my_finance), you will find a file called Rakefile in your project root directory. It has below content in it

#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require File.expand_path('../config/application', __FILE__)

MyFinance::Application.load_tasks # load_tasks method will make all your task available to rake

You can see that, it has self explanatory message at top. So to create, any custom task, we will create a file with .rake extension in lib/tasks folder of our application.

=> Examples of rake tasks.

I will create here different rake task, demonstrating how to write a simple rake task, rake task with arguments and rake task with dependency. let us create a demoexamples.rake file in lib/tasks folder. We will add our custom tasks to this file. Below is the code examples.

namespace :demotask do

  desc "display the current environment of rake"
  task :current_environment do
    puts "You are running rake task in #{Rails.env} environment"
  end

  desc "You are going to meet a person"
  task :meet_a_person do
    puts "I meet a person on the way to my house"
  end

  desc "I will say hello to the person"
  task :say_hello => :meet_a_person do # It means meet_a_person is dependency of say_hello task
    puts "I said HELLO to the person"
  end

  desc "I will say hello to the person after meeting and check environment"
  task :hello_env => [:current_environment, :meet_a_person] do # multiple dependency can be 
                                                               #passed as array
    puts "I said HELLO to the person"
  end

  desc "going to call two of my friend"
  task :call_friend, [:friend1, :friend2] do |t, args| # task with two arguments
    args.with_defaults(:friend1 => "John", :friend2 => "Dough")
    puts t # print t to see what it contain
    puts args # print args to see what it contain and in which format
    puts "Hello #{args.friend1}"
    puts "Hello  #{args.friend2}"
  end

  desc "see what happen when you call a modal method without loading environment"
  task :without_environment do
    puts User.first.full_name
  end

  desc "load environment before operating on any model object"
  task :with_environment => :environment do
    puts User.first.full_name
  end

  desc "count number of records in given model table"
  task :count_records, [:model] => :environment do |t, args| # task with both arguments and dependency
    args.with_defaults(:model => "User" )
    model_calss_name = Object.const_get(args.model) # this is very important as when you#pass argument it come as a string, so you must convert it to model class
    puts "No of records is #{model_calss_name.count}"
  end

end

The point to note above is the use of below concept:

namespace : It will group your task in a namespace, thus avoiding any conflict if task with same name already exists. You can skip it if you want, but use it as good convention

desc : It describe the function your task is going to perform. You can skip it if you want, but use it as good convention

task: it contain the code which perform your desire action. I have just printed simple messages but you can do anything in the do end block

name of the task : task is followed by name of the task as symbol like :meet_a_person,  :say_hello etc

arguments : arguments are passed as array, following the name

dependency : the dependent task to be performed before performing a task is passed as array after =>

=> Listing the custom task

As usual, now when you run rake -vT. It will list the task name with description of what you can do with that task

$ rake -vT

rake demotask:call_friend[friend1,friend2]              # going to call two of my friend
rake demotask:count_records[model]                      # count number of records in given model table
rake demotask:current_environment                       # display the current environment of rake
rake demotask:hello_env                                 # I will say hello to the person after meeting and check environment
rake demotask:meet_a_person                             # You are going to meet a person
rake demotask:say_hello                                 # I will say hello to the person
rake demotask:with_environment                          # load environment before operating on any model object
rake demotask:without_environment                       # see what happen when you call a modal method without loading

=> Running the rake task from terminal

I will show you how to run these task from terminal, with small description where ever needed.

$ rake demotask:current_environment # below is the output , as no environment is passed default development is taken
You are running rake task in development environment

$ rake demotask:current_environment RAILS_ENV=staging # here see how we are passing the environment in which task need to be run
You are running rake task in staging environment

$ rake demotask:current_environment RAILS_ENV=production # this time passing production environment
You are running rake task in production environment

$ rake demotask:meet_a_person # this will just print the message
I meet a person on the way to my house

$ rake demotask:say_hello # see that since meet_a_person is dependency of say_hello, its code is executed first
I meet a person on the way to my house # this message coming from  meet_a_person task, executed first as being a dependency
I said HELLO to the person # hello is printed now, if dependency fail, this task will also fail

$ rake demotask:hello_env #this task have multiple dependency, each called in order they are specified in the task
You are running rake task in development environment
I meet a person on the way to my house
I said HELLO to the person

$ rake demotask:call_friend # you have not passed any argument so default will be printed, also see the value stored in t and args variable
demotask:call_friend # coming from t variable, thus it contain the task name
{:friend1=>”John”, :friend2=>”Dough”} # see that args is generated as a hash
Hello John
Hello  Dough

passing arguments to rake command in rails 3 . when you define any task with argument, while passing it from console, do not use space between different argument otherwise will throw error as below.
$ rake demotask:call_friend[“arun”, “sanjay”]
rake aborted!
Don’t know how to build task ‘demotask:call_friend[arun,’ # see that task name is choped when space encountered , so do not use space between argument
/home/arun/.rvm/gems/ruby-1.9.3-p194@threepiller/gems/rake-10.0.4/lib/rake/task_manager.rb:49:in `[]’
/home/arun/.rvm/gems/ruby-1.9.3-p194@threepiller/gems/rake-10.0.4/lib/rake/application.rb:142:in `invoke_task’
/home/arun/.rvm/gems/ruby-1.9.3-p194@threepiller/gems/rake-10.0.4/lib/rake/application.rb:70:in `run’
(See full trace by running task with –trace)

$ rake demotask:call_friend[“arun”,”sanjay”] # passing argument to rake task
demotask:call_friend
{:friend1=>”arun”, :friend2=>”sanjay”}
Hello arun
Hello  sanjay

$ rake demotask:without_environment # task fail as environment is not loaded so, model, gems, library function etc is not available to rake
rake aborted!
uninitialized constant User

$ rake demotask:with_environment # this will work as this task load environment as its dependency
Jeff Smith

NOTE : for a rake task to use all the methods in your gems, you library, your models i,e available anywhere in your application, you must load environment as its dependency. see with_environment task written above

$ rake demotask:count_records # will count the number of records from User model table
No of records is 13 #my user table have 13 records

$ rake demotask:count_records[Role] # will count the number of records from Role model table, passed here as argument
No of records is 7 #my role table have 7 records

Advertisements

Author: arunyadav4u

over 7 years experience in web development with Ruby on Rails.Involved in all stage of development lifecycle : requirement gathering, planing, coding, deployment & Knowledge transfer. I can adept to any situation, mixup very easily with people & can be a great friend.

2 thoughts on “custom rake task in rails

  1. This was a fantastic post, I’ve been searching the web for good information on rake custom task.
    I spent half a day trying to resolve a problem with running rake custom task with args from the command line.

    The answer was on your post, it was blowing up because I was using spaces in the arguments.

    Thanks very much !!!!!

  2. Thank u so much .. i was trying his article almost half a day .finally i get .

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s