当前位置: 首页 > 工具软件 > Pry > 使用案例 >

用pry阅读ruby源码--以task方法为例

闻人仲渊
2023-12-01

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.

 类似资料: