天天看点

Rails源码笔记-ActiveSupport-core_ext-array

ActiviSupport中包含一些工具类,以及一些对标准类库的扩展。

ActiveSupport的内容都是是独立于rails的,因此也可以在非rails的ruby项目中使用。

获取代码

使用git clone命令可以将代码获取到本地。

git clone git://github.com/rails/rails.git 

我们先从对标准类库的扩展入手,看看ActiveSupport对ruby的标准类库都进行了哪些扩展。

扩展都放在activesupport/lib/active_support/core_ext目录。

进入目录,机会发现rails对ruby的一些基础数据类型都进行了扩展。

进入array文件夹,这里放的是对array的一些扩展。

打开第一个文件,access.rb,看看都做了什么扩展。

class Array 

  # Returns the tail of the array from +position+.  

  #  

  #   %w( a b c d ).from(0)  # => ["a", "b", "c", "d"]  

  #   %w( a b c d ).from(2)  # => ["c", "d"]  

  #   %w( a b c d ).from(10) # => []  

  #   %w().from(0)           # => []  

  def from(position)  

    self[position, length] || []  

  end 

  # Returns the beginning of the array up to +position+.  

  #   %w( a b c d ).to(0)  # => ["a"]  

  #   %w( a b c d ).to(2)  # => ["a", "b", "c"]  

  #   %w( a b c d ).to(10) # => ["a", "b", "c", "d"]  

  #   %w().to(0)           # => []  

  def to(position)  

    first position + 1  

  # Equal to <tt>self[1]</tt>.  

  #   %w( a b c d e).second # => "b"  

  def second  

    self[1]  

  # Equal to <tt>self[2]</tt>.  

  #   %w( a b c d e).third # => "c"  

  def third  

    self[2]  

  # Equal to <tt>self[3]</tt>.  

  #   %w( a b c d e).fourth # => "d"  

  def fourth  

    self[3]  

  # Equal to <tt>self[4]</tt>.  

  #   %w( a b c d e).fifth # => "e"  

  def fifth  

    self[4]  

  # Equal to <tt>self[41]</tt>. Also known as accessing "the reddit".  

  def forty_two  

    self[41]  

end 

你会发现rails的代码很清晰,而且代码中的注释详细而不罗嗦,除去解释方法的用途,一般都会有几个简单的例子,很实用。

这里我将这个文件的全部内容都贴了出来,以后可能会酌情调整,如果有裁剪,大家可以去clone源码,自己对照查看。

关于ruby的api,给大家推荐两个地方。

<a href="http://ruby-doc.org/core-1.9.3/">http://ruby-doc.org/core-1.9.3/</a>

一个是官方的网站,很完整,很全面。

<a href="http://apidock.com/">http://apidock.com/</a>

一个是api笔记网站,任何注册的用户都可以在任何一个api下面添加笔记,挺有意思的。而且不仅包含ruby,还有rails和rspec。

扩展了7个方法

from(position)

返回从给出的位置到末尾的子数组。英文的解释其实更贴切,return  the tail of the array from +position+。从position的位置返回数据的尾巴。

to(position)

和from相反,是从头到position的子数组。

还扩展了second, third, fourth, fifth, forty_two,分别用来返回数据的第二个,第三个,第四个,第五个,第41个元素。

我们再来看看array文件夹中的第二个文件conversions.rb。

这个文件中定义的扩展,主要功能是类型转换。

to_sentence(options = {})

将数组元素用逗号连接成一个句子,最后两个元素使用连接词连接。

可以将数组变成一个句子,默认使用逗号和and连接,包含可选的hash参数options,在参数中可以指定连接数组元素的符号,两个元素的情况下如何连接,多个单词的情况下最后两个如何连接,等等。

to_formatted_s(format =&gt; :default)

将元素的to_s方法返回的结果连接成字符串。指定了:db参数之后,结果就变成了用逗号连接对象的id。

定义别名,to_default_s是to_s的别名。

alias_method :to_default_s, :to_s

alias_method :to_s, :to_formatted_s

关于上面这种用法,我来解释一下,在rails的源码中会多次的遇到。

意思就是先给to_s起了一个别名to_default_s,然后给to_s起了一个别名to_formatted_s。

怎么理解呢,我们先看个例子吧。

class Person 

  def getName 

    puts "andyshi" 

  def getName_new 

    puts "before" 

    getName_old 

    puts "after" 

  alias_method :getName_old, :getName 

  alias_method :getName, :getName_new 

p=Person.new 

p.getName 

我们发现输出的结果是

before 

andyshi 

after 

经过两行的alias_method,对于调用的客户端来说,不需要修改,还是继续调用getName,但是结果发生了变化,前后都加入了新结果。有点aop的效果。

详细解释一下。

首先给原来的getName重命名getName_old,然后定义一个getName_new方法,里面加入其他内容,然后调用getName_old,相当于调用原来的getName,然后将getName指向getName_new。

以前调用getName的地方不用修改,以后也可以继续使用getName,但是调用产生的效果发生了变化。

to_xml(options = {})

返回数组的xml格式字符串。

再来看看另外一个文件extract_options.r。

这里面有两个扩展。

一个是针对hash的。

extractable_options?

返回对象是否可以抽取。是给array的扩展使用的,下面就会介绍到。

一个是针对array的

extract_options!

如果数组的最后一个元素是可抽取的,也就是最后一个元素是否hash,如果是就返回这儿元素,否则就返回一个空的hash,也就是{}。这里面判断是否可抽取,就用到了上面介绍的针对hash的扩展。

再来看grouping.rb文件。

这里面有三个扩展,都是对array的扩展。

in_groups_of(number, fill_with = nil)

就是将数组分组,每组的个数是number,空位使用fill_with来填充。比如说数组长度是10,指定每组3个元素,这样第四组只有一个元素,剩下两个空位,使用fill_with来填充。

in_groups(number, fill_with = nil)

也是将数组分组,number是分组的个数,就是组的个数,空位使用fill_with填充。

splite(value = nil, &amp;block)

将数组分割成子数组,分割的标志是元素的值等于value的值,或者是block指定的条件。

文件prepend_and_append.rb

起了两个别名。

alias_method :append, :&lt;&lt;

alias_method :prepend, :unshift

文件uniq_by.rb

uniq_by(&amp;block)

根据block中的定义返回一个新的唯一的数组。

uniq_by!(&amp;block)

和uniq_by功能一样,但是返回的是修改之后的自己。

文件wrap.rb

self.warp(object)

将object包装成一个数组,如果是数组就直接直接返回object。

上面就是array文件夹中的全部内容。

本文转自 virusswb 51CTO博客,原文链接:http://blog.51cto.com/virusswb/1082531,如需转载请自行联系原作者