用pry閱讀ruby源碼--以task方法爲例

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.

發佈了32 篇原創文章 · 獲贊 5 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章