新手问题 请教下关于如何通过 gem 源码学习来提高

ahr0u · 2014年09月20日 · 最后由 badboy 回复于 2014年09月20日 · 1695 次阅读

目前我具备了 Ruby 和 Rails 基础,基本的 Rails CRUD app 没有问题,扩充需求的时候通过搜索 gem 也能搞定,接下来就是提高了,我相信提高其中一条路便是学习别人的代码,因此我制定的计划是:

  1. 先确定一个希望实现的功能
  2. 搜索现有的 gem,找一个代码量最小的
  3. 看别人怎么实现了,然后自己比照着实现

但这过程中我发现,即使是很简单的 gem,都用了大量 Ruby 或 Rails 的高阶知识,我现在想请教下大家这些高阶知识应该如何补呢?有没有啥书或者教程可以推荐的?或者什么技巧?

问题太宽泛了,我举个实际例子吧。

class ActiveRecord::Base
  def self.record_activities(*actions)
    #association
    options = actions.extract_options!
    if options[:dependent] or options[:association]
      name = options[:association] || :activities
      dependent = options[:dependent] || :nullify
      has_many name, :dependent => dependent, :as => :subject, :class_name => 'Activity'
    end

    #action recording
    actions = [:create, :update] if actions.empty?
    actions.each do |action|
      method = "record_activity_#{action}".to_sym
      define_method method do
        return unless self.class.record_userstamp
        Activity.create(:actor_id => self.class.stamper_class.stamper, :subject => self, :action => action.to_s)
      end
      send("after_#{action}",method) if respond_to?("after_#{action}")
    end
  end
end

如上这段代码就这几行

  1. 我看到extract_options!就卡住了,Google 之,了解到这原来是 Rails ActiveSupport 中的一个方法,很多 Rails 的代码都有用到它。
  2. 接着,到了:association这里又不明白了,如果调用这方法传入的参数中有:association,则将其赋值给 name,然后就赋值:activities?那调用者得传入个:association作为 hash key 的参数?
  3. 而这:activities又是哪里来的呢?之前没有看到过呀,要怎么找到它是在哪里定义的呢?同理:nullify
  4. 跳到下半段,define_method貌似是在动态的创建方法?这是元编程的东西吧?以及sendrespond_to?

希望这个例子都让大家了解到我的问题所在,感谢你的指点 :)

我会在项目目录里面 grep 搜索,如果没有就 Google 看是不是其它库里的。

#1 楼 @Rei 谢谢 Rei,我才看了 happypeter 的 ack 视频,现在正在用 ack 来在当前目录下搜索,貌似将第 2 个问题大概搞懂了

你看的是 rails 的源码吧,确实是很头痛的,似乎没有好的办法可以方便地解决你的这些问题。我个人看的话是在 subl 里打开源码文件夹,看到不明白的莫名共妙的方法,先是CTRL+R看是不是在本文件定义的。而后CTRL+SHIFT+F在整个文件夹内搜索方法名。大不了整个项目内搜索def the_method_name. 一般都是可以找到的。 这样多来几次之后,对那些被include, autoload之类的东西了解得多了之后,一看方法,大致就知道应该是定义在哪里 module 之中,直接就CTRL+T切过去就可以了。

这时候你需要一个 IDE,比如我使用 netbeans 按住 cotrl + 鼠标左键点击方法名。。。神奇的 IDE 就会把你带到源码的世界里。。。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号