homebrew install imagemagick

Posted by wxianfeng Sat, 10 Sep 2011 14:02:00 GMT

环境:mac os x lion
homebrew是用ruby写的脚本,发现和rvm极其相似

安装 homebrew

>/usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"

安装imagemagick

>brew install imagemagick

安装到libtiff 库时 出错

curl: (7) couldn't connect to host
Error: Failure while executing: /usr/bin/curl -f#LA Homebrew\ 0.8\ (Ruby\ 1.8.7-249;\ Mac\ OS\ X\ 10.7.1) ftp://ftp.remotesensing.org/pub/libtiff/tiff-3.9.5.zip -o /Users/wangxianfeng/Library/Caches/Homebrew/libtiff-3.9.5.zip

fixed :

>/usr/bin/curl http://download2.osgeo.org/libtiff/tiff-3.9.5.zip -o ~/Library/Caches/Homebrew/libtiff-3.9.5.zip

再次安装:

>brew install imagemagick

最后测试安装成功:

wxianfeng:inono wangxianfeng$ convert --version
Version: ImageMagick 6.7.1-1 2011-09-10 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2011 ImageMagick Studio LLC
Features: OpenMP

可以查看出brew安装了下面的库:

wxianfeng:inono wangxianfeng$ brew list
imagemagick jasper jpeg libtiff little-cms

see:
https://github.com/mxcl/homebrew/wiki/installation
https://github.com/mxcl/homebrew/pull/5168


北京 798 Ruby/Rails 活动

Posted by wxianfeng Sat, 30 Jul 2011 06:36:00 GMT

时间: 2011-07-24
收获:
发现北京ROR的公司不是一般的多,签到单上看到N多公司,技术上没有太大收获,都是介绍性的,没有实战性的,内容主要涉及: mirah , Mongodb,Erlang,Grape

进程:http://www.surveymonkey.com/s/MSY2L7T

PS : 798 很好玩,很有艺术特色

现场:

093

798 入口

059

Ruby活动地方

054

Rails rumble 创始人

049

现场job board

067

现场

061

清一色老外,清一色Mac

056

介绍Mirah

045

798

083

798

043

798

MORE


ruby yaml 表示数组

Posted by wxianfeng Tue, 01 Mar 2011 13:24:00 GMT

yaml 的语法真是变态 , 表示个数组这么麻烦, 更复杂的数据结构 那不是更麻烦 !!!

yaml 文件:

# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html

one:
  name: MyString
  orgunit_id: 1
  inheritable: false
 # codes 是yaml数组表示方法
 # 缩进只能是两个空格为一级,不能是其他字符
  codes: 
    - 1
    - a
    - 2
    - b
    - 3
    - c

ruby 解析yaml:

ruby-1.9.2-p0 >   file =  "#{Rails.root}/test/fixtures/enumerations.yml"
 => "/usr/local/system/projects/entos/ent_os/test/fixtures/enumerations.yml" 
ruby-1.9.2-p0 > YAML.load File.read(file) 
 => {"one"=>{"name"=>"MyString", "orgunit_id"=>1, "inheritable"=>false, "codes"=>[1, "a", 2, "b", 3, "c"]}} 

不知道怎么写的可以 使用 to_yaml 方法 看一下:

irb(main):001:0> 
=> {"one"=>{"name"=>"MyString", "inheritable"=>false, "orgunit_id"=>1, "codes"=>[1, "a", 2, "b", 3, "c"]}}
irb(main):002:0> require "yaml"
=> true
irb(main):003:0> hsh.to_yaml
=> "--- \none: \n  name: MyString\n  inheritable: false\n  orgunit_id: 1\n  codes: \n  - 1\n  - a\n  - 2\n  - b\n  - 3\n  - c\n"

可读性 更好的 使用 y 方法

ruby-1.9.2-p0 > y hsh
--- 
one: 
  name: MyString
  orgunit_id: 1
  inheritable: false
  codes: 
  - 1
  - a
  - 2
  - b
  - 3
  - c
 => nil 

项目寻人

Posted by wxianfeng Mon, 14 Feb 2011 03:19:00 GMT

公司项目寻人,美工 + Ruby + Java + Flex + Javascript 工程师

招聘帖:

http://chinaonrails.com/topic/view/4746.html

http://www.oschina.net/bbs/thread/15953


ruby rake tips

Posted by wxianfeng Wed, 26 Jan 2011 06:59:00 GMT

环境:ruby 1.9.2 + rake 0.8.7 + rails 3.0.3

今天在写 rake 文件 , 提示我没找到 model Class,问题在于我没加 => :environment , 那为什么加上 => :environment 就可以了 , 研究了下rake:

task :test => :environment do 
end

其中后面的 :environment 也是 一个 task , 也就是说在执行 test 这个 task 之前 会执行 :environment 这个 task,有点像rails controller 中的 before_filter ,那么 :environment 这个task 定义在什么地方,rails project中也没有啊 。。。,定义在 rails 源码中了 ,你在 你的project下执行 rake environment 不会报错的

wxianfeng@ubuntu:/usr/local/system/projects/entos/ent_os$ rake environment --trace 
(in /usr/local/system/projects/entos/ent_os)
** Invoke environment (first_time)
** Execute environment

不过 也看不到 输出什么信息,因为只是加载了 运行环境而已 ,那么从哪里执行的,定义在 project 下 Rakefile 中了

# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require File.expand_path('../config/application', __FILE__)
require 'rake'

EntOs::Application.load_tasks

继续跟踪 load_tasks:

最后 找到了 task environment

   def initialize_tasks
require "rails/tasks"
task :environment do
$rails_rake_task = true
require_environment!
end
end

全部文件 here

所以加载了 environment 也就可以 找到 model Class 了

总结:

1,rake 命名格式

rakefile, Rakefile, rakefile.rb, Rakefile.rb 都可以 ,常用 Rakefile

另外 rails 中使用的话,还可以 使用 .rake 后缀的文件

2,设置命名空间

namespace :test do
end

3,设置默认task

task :default => ["test"]

可以指定多个 task,执行 rake 后 ,默认调用的是 default task

4,指定task执行顺序

task :test => [:hello,:world]

5,查看rake 任务

rake -T  
rake --tasks
rake -T db: # 查看db打头的task

6,跟踪task

rake test --trace 

更多 options

wxianfeng@ubuntu:/usr/local/system/projects/entos/ent_os$ rake -h
rake [-f rakefile] {options} targets...

Options are ...
    -C, --classic-namespace          Put Task and FileTask in the top level namespace
    -D, --describe [PATTERN]         Describe the tasks (matching optional PATTERN), then exit.
    -n, --dry-run                    Do a dry run without executing actions.
    -e, --execute CODE               Execute some Ruby code and exit.
    -p, --execute-print CODE         Execute some Ruby code, print the result, then exit.
    -E, --execute-continue CODE      Execute some Ruby code, then continue with normal task processing.
    -I, --libdir LIBDIR              Include LIBDIR in the search path for required modules.
    -P, --prereqs                    Display the tasks and dependencies, then exit.
    -q, --quiet                      Do not log messages to standard output.
    -f, --rakefile [FILE]            Use FILE as the rakefile.
    -R, --rakelibdir RAKELIBDIR,     Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')
        --rakelib
    -r, --require MODULE             Require MODULE before executing rakefile.
        --rules                      Trace the rules resolution.
    -N, --no-search, --nosearch      Do not search parent directories for the Rakefile.
    -s, --silent                     Like --quiet, but also suppresses the 'in directory' announcement.
    -g, --system                     Using system wide (global) rakefiles (usually '~/.rake/*.rake').
    -G, --no-system, --nosystem      Use standard project Rakefile search paths, ignore system wide rakefiles.
    -T, --tasks [PATTERN]            Display the tasks (matching optional PATTERN) with descriptions, then exit.
    -t, --trace                      Turn on invoke/execute tracing, enable full backtrace.
    -v, --verbose                    Log message to standard output.
    -V, --version                    Display the program version.
    -h, -H, --help                   Display this help message.

DEMO:

wxianfeng@ubuntu:~/test/rake$ cat Rakefile 
desc "Default: test"
task :default => ["r:test"]

namespace :r do 
desc "test" 
task :test  do
        puts "test"
end

desc "test1"
task :test1 => :test do
        puts "test1" 
end

desc "test3"
task :test3 => :test4 do
        puts "test3" 
end 
end

SEE:

http://hi.baidu.com/%D0%C7203/blog/item/ebda2dd09f1d698ea1ec9c7a.html
http://guides.rubyonrails.org/command_line.html
http://ericzouthoughts.wordpress.com/2009/06/20/execute-shell-command-in-ruby-rake-task/


ruby Object#tap and Object#returning

Posted by wxianfeng Wed, 19 Jan 2011 16:29:00 GMT

今天在rails中使用 returning 的时候 log 打出warning:

Object#returning has been deprecated in favor of Object#tap

环境是 ruby 1.9.2 + rails 3.0.3

从warn上看是returning不建议使用,建议使用tap方法,那么tap方法和returning方法有什么不同

Object#tap 方法是 ruby1.8.7 以后加入的,Object#returning 方法是 rails添加的

rails 3.0.3 returning 源码:here

rails 2.3.5 returning源码:

class Object
  # Returns +value+ after yielding +value+ to the block. This simplifies the
  # process of constructing an object, performing work on the object, and then
  # returning the object from a method. It is a Ruby-ized realization of the K
  # combinator, courtesy of Mikael Brockman.
  #
  # ==== Examples
  #
  #  # Without returning
  #  def foo
  #    values = []
  #    values << "bar"
  #    values << "baz"
  #    return values
  #  end
  #
  #  foo # => ['bar', 'baz']
  #
  #  # returning with a local variable
  #  def foo
  #    returning values = [] do
  #      values << 'bar'
  #      values << 'baz'
  #    end
  #  end
  #
  #  foo # => ['bar', 'baz']
  #  
  #  # returning with a block argument
  #  def foo
  #    returning [] do |values|
  #      values << 'bar'
  #      values << 'baz'
  #    end
  #  end
  #  
  #  foo # => ['bar', 'baz']
  def returning(value)
    yield(value)
    value
  end

  # Yields <code>x</code> to the block, and then returns <code>x</code>.
  # The primary purpose of this method is to "tap into" a method chain,
  # in order to perform operations on intermediate results within the chain.
  #
  #   (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.
  #     tap    { |x| puts "array: #{x.inspect}" }.
  #     select { |x| x%2 == 0 }.
  #     tap    { |x| puts "evens: #{x.inspect}" }.
  #     map    { |x| x*x }.
  #     tap    { |x| puts "squares: #{x.inspect}" }
  def tap
    yield self
    self
  end unless Object.respond_to?(:tap)

  # An elegant way to factor duplication out of options passed to a series of
  # method calls. Each method called in the block, with the block variable as
  # the receiver, will have its options merged with the default +options+ hash
  # provided. Each method called on the block variable must take an options
  # hash as its final argument.
  # 
  #   with_options :order => 'created_at', :class_name => 'Comment' do |post|
  #     post.has_many :comments, :conditions => ['approved = ?', true], :dependent => :delete_all
  #     post.has_many :unapproved_comments, :conditions => ['approved = ?', false]
  #     post.has_many :all_comments
  #   end
  #
  # Can also be used with an explicit receiver:
  #
  #   map.with_options :controller => "people" do |people|
  #     people.connect "/people",     :action => "index"
  #     people.connect "/people/:id", :action => "show"
  #   end
  #
  def with_options(options)
    yield ActiveSupport::OptionMerger.new(self, options)
  end
  
  # A duck-type assistant method. For example, Active Support extends Date
  # to define an acts_like_date? method, and extends Time to define
  # acts_like_time?. As a result, we can do "x.acts_like?(:time)" and
  # "x.acts_like?(:date)" to do duck-type-safe comparisons, since classes that
  # we want to act like Time simply need to define an acts_like_time? method.
  def acts_like?(duck)
    respond_to? "acts_like_#{duck}?"
  end

end

可以看到 tap 方法也封装了,为了防止 ruby版本过低 没有tap方法就 添加Object#tap 方法,tap 和 returning本质是一样的,函数体都是调用block闭包,只不过returning需要传递一个参数给闭包,最后返回的就是这个参数,而 tap直接操作self指针,最后返回的也就是self

另外最新rails源码(>rails3.0.3)已经没有 returning方法了,所以以后最好都用tap方法

DEMO1:

require "rubygems"
require "active_support"
# Object#tap 是>ruby1.8.7 有的
# Object#returning 是Rails 封装的方法, rails3.X 已经不建议使用

# Object#tap 可以支持链式(chain)操作
(1..10).tap {
  |x| puts "original: #{x.inspect}"
}.to_a.tap {
  |x| puts "array: #{x.inspect}"
}.select {|x| x%2==0}.tap {
  |x| puts "evens: #{x.inspect}"
}.map {|x| x*x}.tap {
  |x| puts "squares: #{x.inspect}"
}

def object_tap
  {}.tap do |h| # => Hash.new.tap
    h[:a] = 1
    h[:b] =2
  end
end

p object_tap # {:b=>2, :a=>1}

def object_returning
  returning Hash.new do |h| # 注意这里不能用 {}  , 放在 returning 方法后面 当作成 block闭包了
    h[:a] = 1
    h[:b] = 2
  end  
end

p object_returning # {:b=>2, :a=>1}

DEMO2:

require "rubygems"
require "active_support"

class Hash  
  def shift_value_tap_self
    self.tap do |h|
      h.each { |k,v| v.shift if v.is_a?(Array) }
    end
  end
  def shift_value_tap
    {}.tap do |h|
      self.each { |k,v|  v.is_a?(Array) ? h[k] = v.shift : h[k] = v } 
    end
  end

  def shift_value_returning
    returning Hash.new do |h|
      self.each { |k,v|  v.is_a?(Array) ? h[k] = v.shift : h[k] = v } 
    end
  end
  def shift_value_returning_self
    returning self do |h|
      h.each { |k,v| v.shift if v.is_a?(Array) }
    end
  end
end

hsh = {"a"=>[1,2,3],"b"=>["g","f","w"],"c"=>"fuck_china"}
hsh1 = {"a"=>[1,2,3],"b"=>["g","f","w"],"c"=>"fuck_china"}
hsh2 = {"a"=>[1,2,3],"b"=>["g","f","w"],"c"=>"fuck_china"}
hsh3 = {"a"=>[1,2,3],"b"=>["g","f","w"],"c"=>"fuck_china"}
p hsh.shift_value_tap # {"a"=>1, "b"=>"g", "c"=>"fuck_china"}
p hsh1.shift_value_returning # {"a"=>1, "b"=>"g", "c"=>"fuck_china"}
p hsh2.shift_value_tap_self # {"a"=>[2, 3], "b"=>["f", "w"], "c"=>"fuck_china"}
p hsh3.shift_value_returning_self # {"a"=>[2, 3], "b"=>["f", "w"], "c"=>"fuck_china"}

SEE:
http://blog.rubybestpractices.com/posts/gregory/011-tap-that-hash.html
http://www.simonecarletti.com/blog/2010/09/rails-3-beware-the-tap-pattern/
http://fuliang.javaeye.com/blog/857163


ruby string to class

Posted by wxianfeng Mon, 17 Jan 2011 09:53:00 GMT

环境:ruby 1.9.2

有这样一个需求, 给你 任意一个字符串,把它转化为类,网上大多数的 解决办法是 下面三种:

Kernel.const_get(:User) # Object.const_get(:User)
eval(’User’)
‘User’.constantize

但是上面三种方法, 这个 User 事先必须是初始化的,不然会报错,如下:

Object.const_get(:User) # uninitialized constant User (NameError)

所以需要加个判断 这个 Class 有没有初始化,没有的话 再set 一个Class

require "rails/all"

def Kernel.const_missing(name)
  Object.const_set(name,Class.new)
end
#p Kernel.const_get("baoxiaos".to_sym) # wrong constant name baoxiaos (NameError)
p Kernel.const_get("baoxiaos".classify.to_sym) # Baoxiao , const的首字母必须大写
p Kernel.constants # []
p Object.constants.include?(:UBaoxiao) # true

刚开始把这个 const 定义在 Object 里:

require "rails/all"

def Object.const_missing(name)
  Object.const_set(name,Class.new)
end

#p Object.const_get("baoxiaos".to_sym) # wrong constant name baoxiaos (NameError)
p Object.const_get("baoxiaos".classify.to_sym)

发现 用在 rails 中后 , rails 处处报错,可能 怪我重写了 Object.const_missing 导致的 ……..

上面方法的原理是 当找不到 const的时候 执行了

  Object.const_set(name,Class.new)

那么 name 就变成是 Class 的实例了 , 为什么定义在 Kernel 中的 const_missing ,Object 也可以访问到,需要注意 Object,Kernel 之间的关系,Object 是 inluce Kernel 的,如下:

class Object
include Kernel
end

SEE:

http://niczsoft.com/2010/01/string-to-class-in-ruby-on-rails/
http://www.ruby-forum.com/topic/96222


ruby instance_variables

Posted by wxianfeng Tue, 11 Jan 2011 05:52:00 GMT

环境:ruby 1.9.2 + ubuntu 10.10

instance_variables 得到当前 对象已经开辟内存空间的实例变量,疑惑在这里

class Foo

  attr_accessor :sex,:birthday  

end

p Foo.new.instance_variables # => []

刚开始不理解,怎么是 空……..

后来想了想,因为 ruby 是 动态的解释型的语言,如果没有 给实例变量赋值 的话,是不会开辟内存空间的,所以 instance_variables 只能得到已经开辟内存空间的 实例变量,
但是如果是 编译型的静态语言 则不然,例如java ,实例变量 声明了 就会开辟内存空间了

DEMO1:

# ruby version : 1.9.2

class Foo

  attr_accessor :sex,:birthday # attr_accessor ruby里封装的method  

end

p Foo.new.instance_variables # => []

f = Foo.new
p f.sex #=> nil
f.sex = 'M' 
p f.instance_variables #=>  [:@sex]
p f.inspect # => "#<Foo:0x85ead8c @sex=\"M\">"

b = Foo.new
b.birthday = nil # 注意赋值为nil,也开辟了内存空间
p b.instance_variables # => [:@birthday]
p b.inspect # => "#<Foo:0x9dca358 @birthday=nil>"

DEMO2:

class Foo
  
  def initialize
    @name = 'wxianfeng'
  end

  def bar # => as getter method
    @name
  end

end

f = Foo.new
p f.instance_variables #=> [:@name]
p f.inspect #=> "#<Foo:0x8aa7c08 @name=\"wxianfeng\">"
p f.name # =>  undefined method `name' for #<Foo:0x99adf7c @name="wxianfeng">
p f.bar # => "wxianfeng"

ruby 源码:

    # obj.instance_variables    => array
    #
    #
    # Returns an array of instance variable names for the receiver. Note
    # that simply defining an accessor does not create the corresponding
    # instance variable.
    #
    #    class Fred
    #      attr_accessor :a1
    #      def initialize
    #        @iv = 3
    #      end
    #    end
    #    Fred.new.instance_variables   #=> ["@iv"]
    #
    #
    def instance_variables
      # This is just a stub for a builtin Ruby method.
      # See the top of this file for more info.
    end

SEE:
http://www.megasolutions.net/ruby/instance_variables-doesnt-return-unassigned-variables-68358.aspx


ruby正则 \1 和 $1 区别 和 结合gsub的用法

Posted by wxianfeng Tue, 28 Dec 2010 08:47:00 GMT

环境:ruby 1.9

\1 和 $1 在用 ruby 正则的时候 经常会用到 , 那么有什么区别呢,今天 来梳理一下:

\1 : 是 向后引用 , 常使用在 sub , gsub 中
$1 : 是 ruby 里的全局变量

看几个demo:

demo:

"ab12cd12".gsub(/(\d+)cd(\1)/,"")   # => "ab"

这个正则就相当于 /(\d+)cd12/  ,因为 \1 引用的是 前面的 (\d+) ,而前面的 (\d+) 匹配出来的结果是  12

"ab12cd".gsub(/(\d+)/,'34\1')  #  => "ab3412cd"
p "ab12cd".gsub(/(\d+)/,'34\1') # "ab3412cd"
p $1  # "12"
p "ab56cd".gsub(/(\d+)/,"78#{$1}") # "ab7812cd" , 这个时候的 $1 为 上面的 12
p "ab12cd".gsub(/(\d+)/,'34\1') # "ab3412cd"
p $1  # "12"
str = "ab56cd".gsub(/(\d+)/) do |ele|
  "78#{$1}" # 这里的 $1 是 56
end
p str # "ab7856cd"
p "ab56cd".gsub(/(\d+)/,"78#{$1}") # "ab78cd" 这里的 $1 是 nil
str = "ab56cd".gsub(/(\d+)/) do |ele|
  "78#{$1}"
end

p str # "ab7856cd"

得出结论:

1,\1 和 $1 是两个 不同的用法
2,特别注意 $1 在 gsub中 block 中,和 写在replacement 中 是不一样的 , \1 用在 replacement 中 ,$1 用在 block 中 ,这个源码中已经说明了
3,\1 必须用单引号

看下源码中的解释:

#     str.gsub(pattern, replacement)       => new_str
  #     str.gsub(pattern) {|match| block }   => new_str
  #
  #
  # Returns a copy of <i>str</i> with <em>all</em> occurrences of <i>pattern</i>
  # replaced with either <i>replacement</i> or the value of the block. The
  # <i>pattern</i> will typically be a <code>Regexp</code>; if it is a
  # <code>String</code> then no regular expression metacharacters will be
  # interpreted (that is <code>/\d/</code> will match a digit, but
  # <code>'\d'</code> will match a backslash followed by a 'd').
  #
  # If a string is used as the replacement, special variables from the match
  # (such as <code>$&</code> and <code>$1</code>) cannot be substituted into it,
  # as substitution into the string occurs before the pattern match
  # starts. However, the sequences <code>\1</code>, <code>\2</code>, and so on
  # may be used to interpolate successive groups in the match.
  #
  # In the block form, the current match string is passed in as a parameter, and
  # variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
  # <code>$&</code>, and <code>$'</code> will be set appropriately. The value
  # returned by the block will be substituted for the match on each call.
  #
  # The result inherits any tainting in the original string or any supplied
  # replacement string.
  #
  #    "hello".gsub(/[aeiou]/, '*')              #=> "h*ll*"
  #    "hello".gsub(/([aeiou])/, '<\1>')         #=> "h<e>ll<o>"
  #    "hello".gsub(/./) {|s| s[0].to_s + ' '}   #=> "104 101 108 108 111 "
  #
  #
  def gsub(pattern, replacement)
    # This is just a stub for a builtin Ruby method.
    # See the top of this file for more info.
  end

replacement 时:

 # If a string is used as the replacement, special variables from the match
# (such as <code>$&</code> and <code>$1</code>) cannot be substituted into it,
# as substitution into the string occurs before the pattern match
# starts. However, the sequences <code>\1</code>, <code>\2</code>, and so on
# may be used to interpolate successive groups in the match.

block 时:

 # In the block form, the current match string is passed in as a parameter, and
# variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
# <code>$&</code>, and <code>$’</code> will be set appropriately. The value
# returned by the block will be substituted for the match on each call.

http://stackoverflow.com/questions/288573/1-and-1-in-ruby


ruby module extend self

Posted by wxianfeng Tue, 21 Dec 2010 06:39:00 GMT

环境:ruby 1.9.2 + ubuntu 10.10 + rails 3.0.3

我们知道 ruby 中 扩展class ,写公用方法 ,或者 利用命名空间 来模块化 ,都是通过 module 来实现的 , 今天 看 rails 中 camelize 方法的源码的时候 , 发现 module 这样写的…..

active_support/inflector/methods.rb

module ActiveSupport
  # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
  # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
  # in inflections.rb.
  #
  # The Rails core team has stated patches for the inflections library will not be accepted
  # in order to avoid breaking legacy applications which may be relying on errant inflections.
  # If you discover an incorrect inflection and require it for your application, you'll need
  # to correct it yourself (explained below).
  module Inflector
    extend self

    # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
    # is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
    #
    # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
    #
    # Examples:
    #   "active_record".camelize                # => "ActiveRecord"
    #   "active_record".camelize(:lower)        # => "activeRecord"
    #   "active_record/errors".camelize         # => "ActiveRecord::Errors"
    #   "active_record/errors".camelize(:lower) # => "activeRecord::Errors"
    #
    # As a rule of thumb you can think of +camelize+ as the inverse of +underscore+,
    # though there are cases where that does not hold:
    #
    #   "SSLError".underscore.camelize # => "SslError"
    def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
      if first_letter_in_uppercase
        lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
      else
        lower_case_and_underscored_word.to_s[0].chr.downcase + camelize(lower_case_and_underscored_word)[1..-1]
      end
    end

    # Makes an underscored, lowercase form from the expression in the string.
    #
    # Changes '::' to '/' to convert namespaces to paths.
    #
    # Examples:
    #   "ActiveRecord".underscore         # => "active_record"
    #   "ActiveRecord::Errors".underscore # => active_record/errors
    #
    # As a rule of thumb you can think of +underscore+ as the inverse of +camelize+,
    # though there are cases where that does not hold:
    #
    #   "SSLError".underscore.camelize # => "SslError"
    def underscore(camel_cased_word)
      word = camel_cased_word.to_s.dup
      word.gsub!(/::/, '/')
      word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
      word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
      word.tr!("-", "_")
      word.downcase!
      word
    end

    # Replaces underscores with dashes in the string.
    #
    # Example:
    #   "puni_puni" # => "puni-puni"
    def dasherize(underscored_word)
      underscored_word.gsub(/_/, '-')
    end

    # Removes the module part from the expression in the string.
    #
    # Examples:
    #   "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections"
    #   "Inflections".demodulize                                       # => "Inflections"
    def demodulize(class_name_in_module)
      class_name_in_module.to_s.gsub(/^.*::/, '')
    end

    # Creates a foreign key name from a class name.
    # +separate_class_name_and_id_with_underscore+ sets whether
    # the method should put '_' between the name and 'id'.
    #
    # Examples:
    #   "Message".foreign_key        # => "message_id"
    #   "Message".foreign_key(false) # => "messageid"
    #   "Admin::Post".foreign_key    # => "post_id"
    def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
      underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
    end

    # Ruby 1.9 introduces an inherit argument for Module#const_get and
    # #const_defined? and changes their default behavior.
    if Module.method(:const_get).arity == 1
      # Tries to find a constant with the name specified in the argument string:
      #
      #   "Module".constantize     # => Module
      #   "Test::Unit".constantize # => Test::Unit
      #
      # The name is assumed to be the one of a top-level constant, no matter whether
      # it starts with "::" or not. No lexical context is taken into account:
      #
      #   C = 'outside'
      #   module M
      #     C = 'inside'
      #     C               # => 'inside'
      #     "C".constantize # => 'outside', same as ::C
      #   end
      #
      # NameError is raised when the name is not in CamelCase or the constant is
      # unknown.
      def constantize(camel_cased_word)
        names = camel_cased_word.split('::')
        names.shift if names.empty? || names.first.empty?

        constant = Object
        names.each do |name|
          constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
        end
        constant
      end
    else
      def constantize(camel_cased_word) #:nodoc:
        names = camel_cased_word.split('::')
        names.shift if names.empty? || names.first.empty?

        constant = Object
        names.each do |name|
          constant = constant.const_defined?(name, false) ? constant.const_get(name) : constant.const_missing(name)
        end
        constant
      end
    end

    # Turns a number into an ordinal string used to denote the position in an
    # ordered sequence such as 1st, 2nd, 3rd, 4th.
    #
    # Examples:
    #   ordinalize(1)     # => "1st"
    #   ordinalize(2)     # => "2nd"
    #   ordinalize(1002)  # => "1002nd"
    #   ordinalize(1003)  # => "1003rd"
    def ordinalize(number)
      if (11..13).include?(number.to_i % 100)
        "#{number}th"
      else
        case number.to_i % 10
          when 1; "#{number}st"
          when 2; "#{number}nd"
          when 3; "#{number}rd"
          else    "#{number}th"
        end
      end
    end
  end
end

发现 了这样的写法

module A
module B
extend self
.....
end
end

extend self 有何作用?

先来看个demo:

module Foo
  module Bar
      extend self # self => Foo::Bar

    def hello
      p "hello"
    end
  end
end

class Klass
  include Foo::Bar
end

Klass.new.hello #  "hello"
Foo::Bar.hello # "hello"
Klass.hello # undefined method `hello' for Klass:Class (NoMethodError)

发现 module 中的方法 可以当作模块方法 直接被Module调用 , 被include 到class 中后 , 依然还是 class 的实例方法 , 恩,不错,以后 像下面 这样的写法, 都要 改改了:

module A
def self.foo
end
end

改成这样:

module A
extend self
def foo
end
end

demo里的extend self 其实就是 Foo::Bar.extend(Foo::Bar)

所以 可以 更动态的 写成这样:

module Foo
  module Bar     

    def hello
      p "hello"
    end
  end
end

class Klass
  include Foo::Bar
end

Foo::Bar.extend(Foo::Bar)

Klass.new.hello #  "hello"
Foo::Bar.hello # "hello"
Klass.hello # undefined method `hello' for Klass:Class (NoMethodError)

see:
http://www.railsfire.com/article/extending-self-module