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

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

 

获取代码

rails的源码位于https://github.com/rails/rails

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

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

 

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

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

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

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

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

 

 
  
  1. class Array 
  2.   # Returns the tail of the array from +position+.  
  3.   #  
  4.   #   %w( a b c d ).from(0)  # => ["a", "b", "c", "d"]  
  5.   #   %w( a b c d ).from(2)  # => ["c", "d"]  
  6.   #   %w( a b c d ).from(10) # => []  
  7.   #   %w().from(0)           # => []  
  8.   def from(position)  
  9.     self[position, length] || []  
  10.   end 
  11.  
  12.   # Returns the beginning of the array up to +position+.  
  13.   #  
  14.   #   %w( a b c d ).to(0)  # => ["a"]  
  15.   #   %w( a b c d ).to(2)  # => ["a", "b", "c"]  
  16.   #   %w( a b c d ).to(10) # => ["a", "b", "c", "d"]  
  17.   #   %w().to(0)           # => []  
  18.   def to(position)  
  19.     first position + 1  
  20.   end 
  21.  
  22.   # Equal to <tt>self[1]</tt>.  
  23.   #  
  24.   #   %w( a b c d e).second # => "b"  
  25.   def second  
  26.     self[1]  
  27.   end 
  28.  
  29.   # Equal to <tt>self[2]</tt>.  
  30.   #  
  31.   #   %w( a b c d e).third # => "c"  
  32.   def third  
  33.     self[2]  
  34.   end 
  35.  
  36.   # Equal to <tt>self[3]</tt>.  
  37.   #  
  38.   #   %w( a b c d e).fourth # => "d"  
  39.   def fourth  
  40.     self[3]  
  41.   end 
  42.  
  43.   # Equal to <tt>self[4]</tt>.  
  44.   #  
  45.   #   %w( a b c d e).fifth # => "e"  
  46.   def fifth  
  47.     self[4]  
  48.   end 
  49.  
  50.   # Equal to <tt>self[41]</tt>. Also known as accessing "the reddit".  
  51.   def forty_two  
  52.     self[41]  
  53.   end 
  54. end 

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

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

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

http://ruby-doc.org/core-1.9.3/

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

http://apidock.com/

一个是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 => :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。

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

 

 
      
  1. class Person 
  2.  
  3.   def getName 
  4.     puts "andyshi" 
  5.   end 
  6. end 
  7.  
  8. class Person 
  9.  
  10.   def getName_new 
  11.     puts "before" 
  12.     getName_old 
  13.     puts "after" 
  14.   end 
  15.  
  16.   alias_method :getName_old:getName 
  17.   alias_method :getName:getName_new 
  18. end 

 

 
  
  1. p=Person.new 
  2.  
  3. p.getName 

 

我们发现输出的结果是

 

 
  
  1. before 
  2.  
  3. andyshi 
  4.  
  5. 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, &block)

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

 

文件prepend_and_append.rb

起了两个别名。

alias_method :append, :<<

alias_method :prepend, :unshift

 

文件uniq_by.rb

uniq_by(&block)

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

 

uniq_by!(&block)

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

 

文件wrap.rb

self.warp(object)

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

 

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