rails项目中有个目录 lib/tasks,里面定义了一个rake任务:
task hello: :hello do
puts “hello”
end
看到这里的时候,是不是可能会对 task 方法产生一些兴趣?
可以在rails项目的Gemfile中加入 pry这个强大的工具,然后一步步找到这个task方法的本质。
1,在task中加入断点:
binding.pry
2,断点中用 show-method 方法
用show-method按图索骥,可以层层揭开 task 的面纱。
[33] pry(main)>
[34] pry(main)> show-method task
From: /home/liukun/.rvm/gems/ruby-2.1.1@zhe800_zhaoshang/gems/rake-10.0.4/lib/rake/dsl_definition.rb @ line 31:
Owner: Rake::DSL
Visibility: private
Number of lines: 3
def task(*args, &block)
Rake::Task.define_task(*args, &block)
end
[35] pry(main)> show-method Rake::Task.define_task
From: /home/liukun/.rvm/gems/ruby-2.1.1@zhe800_zhaoshang/gems/rake-10.0.4/lib/rake/task.rb @ line 350:
Owner: #<Class:Rake::Task>
Visibility: public
Number of lines: 3
def define_task(*args, &block)
Rake.application.define_task(self, *args, &block)
end
[36] pry(main)> show-method Rake.application.define_task
From: /home/liukun/.rvm/gems/ruby-2.1.1@zhe800_zhaoshang/gems/rake-10.0.4/lib/rake/task_manager.rb @ line 23:
Owner: Rake::TaskManager
Visibility: public
Number of lines: 13
def define_task(task_class, *args, &block)
task_name, arg_names, deps = resolve_args(args)
task_name = task_class.scope_name(@scope, task_name)
deps = [deps] unless deps.respond_to?(:to_ary)
deps = deps.collect {|d| d.to_s }
task = intern(task_class, task_name)
task.set_arg_names(arg_names) unless arg_names.empty?
if Rake::TaskManager.record_task_metadata
add_location(task)
task.add_description(get_description(task))
end
task.enhance(deps, &block)
end
[37] pry(main)>
3, environment的作用是什么?
用来通知Rake需要加载rails环境。
参考:
http://stackoverflow.com/questions/7044714/whats-the-environment-task-in-rake
4,进一步理解 environment
http://jasonseifer.com/2010/04/06/rake-tutorial
task :turn_off_alarm do
puts "Turned off alarm. Would have liked 5 more minutes, though."
end
task :groom_myself do
puts "Brushed teeth."
puts "Showered."
puts "Shaved."
end
task :make_coffee do
cups = ENV["COFFEE_CUPS"] || 2
puts "Made #{cups} cups of coffee. Shakes are gone."
end
task :walk_dog do
puts "Dog walked."
end
task :ready_for_the_day => [:turn_off_alarm, :groom_myself, :make_coffee, :walk_dog] do
puts "Ready for the day!"
end
By running the ready_for_the_day task it notices that the turn_off_alarm, groom_myself, make_coffee, and walk_dog tasks are all prerequisites of the ready_for_the_day task. Then it runs them all in the appropriate order.