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