ruby 对象模型

Posted by wxianfeng Mon, 07 Jan 2013 21:54:00 GMT

环境: mac 10.8 + ruby 1.9.2
ruby 对象模型非常重要, 不了解ruby对象模型, 不算真正掌握ruby, ruby 号称一切都是对象, why? 当你知道对象模型就清楚了.

说到ruby对象模型, 这张图是ruby基本的类关系.

class 表示实例关系(水平),super 表示继承关系(垂直),从图中可以看出

objmy 是 MyClass 的实例
MyClass 是 Class 的实例
Class 的父类是 Module
MyClass 的父类是 Object
Object 的父类是 BasicObject (ruby1.9)
MyClass include 模块M后,相当于在继承祖先链正上方继承该模块
Object include 模块Kernel
Module类的superclass 是Object
所有都可以在irb看到:

ruby-1.9.2-p290 :001 > MyClass = Class.new
 => MyClass 
ruby-1.9.2-p290 :002 > objmy = MyClass.new
 => #<MyClass:0x007f9ea1aba080> 
ruby-1.9.2-p290 :003 > objmy.class
 => MyClass 
ruby-1.9.2-p290 :004 > MyClass.class
 => Class 
ruby-1.9.2-p290 :005 > MyClass.superclass
 => Object 
ruby-1.9.2-p290 :006 > Class.class
 => Class 
ruby-1.9.2-p290 :007 > Class.superclass
 => Module 
ruby-1.9.2-p290 :008 > Module.class
 => Class 
ruby-1.9.2-p290 :009 > Module.superclass
 => Object 
ruby-1.9.2-p290 :010 > Object.class
 => Class 
ruby-1.9.2-p290 :011 > Object.superclass
 => BasicObject 
ruby-1.9.2-p290 :012 > BasicObject.class
 => Class 
ruby-1.9.2-p290 :013 > BasicObject.superclass
 => nil 

所以掌握了 Object,Module,Class 三者之间关系很重要, ruby 很多gem里的方法都是打开 Object来注入方法的.这样下面任何对象就都有该实例方法了.

demo:

#!/usr/bin/env ruby

class Object
        def foo
                p "im foo"
        end
end

MyClass = Class.new
objmy = MyClass.new
objmy.foo # im foo

有一个gem可以查看ruby对象模型, drx
安装:

>gem install drx
>brew install graphviz

使用:

wxianfeng-2:entos wangxianfeng$ irb
ruby-1.9.2-p290 :001 > require 'drx'
 => true 
ruby-1.9.2-p290 :002 > MyClass = Class.new
 => MyClass 
ruby-1.9.2-p290 :003 > objmy = MyClass.new
 => #<MyClass:0x007fcd1221b2e0> 
ruby-1.9.2-p290 :004 > objmy.see

出现下图:

这样就更加一目了然了.但是注意上图引入了eigenclass概念, 想了解 ruby 中方法查找的话, 就必须要知道了, 下回分解.


ruby 汉字转拼音

Posted by wxianfeng Tue, 20 Nov 2012 04:30:00 GMT

很久以前从项目中抽取出来的 汉字转拼音的 gem, 今天介绍下使用方法.

功能

  • 首字母支持
  • 全拼支持
  • 多音字支持
  • 其它字符默认输出

Gemfile:

gem 'hanzi_to_pinyin', '0.8.0', require: 'hanzi_to_pinyin'

使用demo

$ HanziToPinyin.hanzi_to_pinyin("喜欢Ruby") => "xhruby"
$ HanziToPinyin.hanzi_2_pinyin("喜欢Ruby") => "xhruby"

$ HanziToPinyin.is_hanzi?("") => true
$ HanziToPinyin.is_hanzi?("a") => false

# 多音字,分隔 字字之间;分隔,字母丢弃
$ HanziToPinyin.hanzi_2_py("我们") => "wo;men"
$ HanziToPinyin.hanzi_2_py("查理Smith") => "cha,zha;li"
$ HanziToPinyin.hanzi_2_py("测试1") => "ce;shi;1"
$ HanziToPinyin.hanzi_2_py("测_试") => "ce;_;shi"
$ HanziToPinyin.hanzi_2_py("测-试") => "ce;-;shi"
$ HanziToPinyin.hanzi_2_py(2) =>  "2"

$ HanziToPinyin.is_number?("1".ord) => true
$ HanziToPinyin.is_number?("a".ord) => false

$ HanziToPinyin.is_underline?("_".ord) => true
$ HanziToPinyin.is_underline?("豆豆") => false
$ HanziToPinyin.is_dash?("-".ord) => true

更多介绍可以看 github 主页

HERE

另外也被翻译成了 nodejs module

nodejs


ruby Array#pack String#unpack 实例

Posted by wxianfeng Sat, 26 May 2012 21:25:00 GMT

最近项目中常用到 Array#pack, String#unpack 方法,在此总结下:

Array#pack, String#unpack 可以实现不同编码之间的处理, 可以处理字节级, bit 级的一些二进制格式.

字节编码, ruby里主要是 “\nnn” 和 “\xnn” 的形式, nnn 是八进制数字, nn 是十六进制, 可以从 <<ruby编程语言>> 这本书看到相关信息.

截了张书中的图:

例子:
ASCII 码值: 0123456789
字节编码:
“\000\001\002\003\004\005\006\007\010\011” (八进制)
“\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09” (十六进制)

另外 ascii 码值是 7,8,9 的在ruby中是转义序列 “\a”, “\b”, “\t”, 所以字节编码也可以写成
\x00\x01\x02\x03\x04\x05\x06\a\b\t

1.9.2p290 :198 > a = [0,1,2,3,4,5,6,7,8,9]
 => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1.9.2p290 :199 > a.pack("c*")
 => "\x00\x01\x02\x03\x04\x05\x06\a\b\t"
1.9.2p290 :200 > "\x00\x01\x02\x03\x04\x05\x06\a\b\t" == "\000\001\002\003\004\005\006\007\010\011"
 => true
1.9.2p290 :201 > "\011" == "\x09"
 => true
1.9.2p290 :202 > "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" == "\000\001\002\003\004\005\006\007\010\011"
 => true

下面来看一些实例,以字符模板来讲

1, M

M         | String  | quoted printable, MIME encoding (see RFC2045)

字符串和 quoted printable 编码之间转换,常用在邮件编码中

Array#pack
ruby-1.9.2-p290 :132 > ["[www.wxianfeng.com]欢迎您注册,请您激活"].pack("M")
 => "[www.wxianfeng.com]=E6=AC=A2=E8=BF=8E=E6=82=A8=E6=B3=A8=E5=86=8C,=E8=AF=B7=\n=E6=82=A8=E6=BF=80=E6=B4=BB=\n" 

可以看到 每76个字符就多了一个 =\n , 所以如果是用在邮件的 Subject 的中的话, 应该是

["str"].pack("M").gsub(/=\n/,"")

完整的邮件Subject编码应该是 像这样:

value = ["[#{site}]请激活您的帐号"].pack("M").gsub(/=\n/, "")
subject = "=?UTF-8?Q?#{value}?="
String#unpack
ruby-1.9.2-p290 :153 > "[www.wxianfeng.com]=E6=AC=A2=E8=BF=8E=E6=82=A8=E6=B3=A8=E5=86=8C,=E8=AF=B7=\n=E6=82=A8=E6=BF=80=E6=B4=BB=\n".unpack("M")
 => ["[www.wxianfeng.com]\xE6\xAC\xA2\xE8\xBF\x8E\xE6\x82\xA8\xE6\xB3\xA8\xE5\x86\x8C,\xE8\xAF\xB7\xE6\x82\xA8\xE6\xBF\x80\xE6\xB4\xBB"] 

2, m

m         | String  | base64 encoded string (see RFC 2045, count is width)
             |         | (if count is 0, no line feed are added, see RFC 4648)

字符串和 Base64 编码之间转换

Array#pack
ruby-1.9.2-p290 :133 > ["[www.wxianfeng.com]欢迎您注册,请您激活"].pack("m")
 => "W3d3dy53eGlhbmZlbmcuY29tXeasoui/juaCqOazqOWGjCzor7fmgqjmv4Dm\ntLs=\n"

base64编码也可以用在邮件编码中,例如用在Subject中就是这样:

value = ["[#{site}]请激活您的帐号"].pack("M").gsub(/=\n/, "")
subject = "=?UTF-8?B?#{value}?="
String#unpack
ruby-1.9.2-p290 :155 > "W3d3dy53eGlhbmZlbmcuY29tXeasoui/juaCqOazqOWGjCzor7fmgqjmv4Dm\ntLs=\n".unpack("m")
 => ["[www.wxianfeng.com]\xE6\xAC\xA2\xE8\xBF\x8E\xE6\x82\xA8\xE6\xB3\xA8\xE5\x86\x8C,\xE8\xAF\xB7\xE6\x82\xA8\xE6\xBF\x80\xE6\xB4\xBB"]

3, L

 L         | Integer | 32-bit unsigned, native endian (uint32_t)

整型(ASCII)和二进制字符串相互转化,int是32为无符号的,占4个字节

Array#pack
ruby-1.9.2-p290 :139 > [65].pack("L")
 => "A\x00\x00\x00"

String#unpack
ruby-1.9.2-p290 :140 > "A\x00\x00\x00".unpack("L")
 => [65] 

4, c

c         | Integer | 8-bit signed (signed char)

整型(ASCII)和二进制字符串相互转化,int 是8位有符号的,占一个字节

Array#pack
ruby-1.9.2-p290 :142 > [77].pack("c")
 => "M" 

String#unpack
ruby-1.9.2-p290 :143 > "M".unpack("c")
 => [77] 

5, Q

Q         | Integer | 64-bit unsigned, native endian (uint64_t)

整型和二进制字符串相互转化,int是64位无符号的,占8字节

Array#pack
ruby-1.9.2-p290 :149 > [1338053358065].pack("Q")
 => "\xF1\xF11\x8A7\x01\x00\x00" 

String#unpack
ruby-1.9.2-p290 :150 > "\xF1\xF11\x8A7\x01\x00\x00".unpack("Q")
 => [1338053358065]

6, S

S         | Integer | 16-bit unsigned, native endian (uint16_t)

整型和二进制字符串转化,int是16位无符号的,占2个字节

Array#pack
ruby-1.9.2-p290 :151 > [6].pack("S")
 => "\x06\x00" 

String#unpack
ruby-1.9.2-p290 :152 > "\x06\x00".unpack("S")
 => [6] 

http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-pack
http://www.ruby-doc.org/core-1.9.3/String.html#method-i-unpack
http://www.cnblogs.com/baochun968/archive/2011/10/19/2218008.html


thin 开机自启动

Posted by wxianfeng Sat, 21 Apr 2012 17:08:00 GMT

环境:
ubuntu server 10.04 + rvm + ruby 1.9.2 + rails 3.0.3

本来自启动是很简单的操作,可是今天为了让服务器上一个应用自启动,应用服务器用的是 thin, thin怎么也不能自启动,估计是rvm的问题,最后使用rvm wrapper解决了.

我以普通用户登录的ubuntu

安装 thin init.d 脚本

>sudo thin install

如果提示sudo thin 找不到 ,可以使用:

>rvmsudo thin install

这句命令实质在 /etc/init.d 下新建了 thin脚本

#!/bin/sh
### BEGIN INIT INFO
# Provides:          thin
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      S 0 1 6
# Short-Description: thin initscript
# Description:       thin
### END INIT INFO

# Original author: Forrest Robertson

# Do NOT "set -e"

# DAEMON=/usr/local/rvm/gems/ruby-1.9.2-p318/bin/thin
DAEMON=/usr/local/rvm/bin/bootup_thin
SCRIPT_NAME=/etc/init.d/thin
CONFIG_PATH=/etc/thin

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

case "$1" in
  start)
        $DAEMON start --all $CONFIG_PATH
        ;;
  stop)
        $DAEMON stop --all $CONFIG_PATH
        ;;
  restart)
        $DAEMON restart --all $CONFIG_PATH
        ;;
  *)
        echo "Usage: $SCRIPT_NAME {start|stop|restart}" >&2
        exit 3
        ;;
esac

:

设置 thin 开机自启动

>sudo update-rc.d -f thin defaults

然后把你的thin.yml配置文件放到 /etc/thin/ 下,看下我的:

wxianfeng@SNDA-192-168-2-15:~$ cat /etc/thin/thin.yml 
--- 
chdir: /data/projects/project_manager
environment: production
address: 0.0.0.0
port: 3000
timeout: 30
log: log/thin.log
pid: tmp/pids/thin.pid
max_conns: 1024
max_persistent_conns: 512
require: []

wait: 30
servers: 6
daemonize: true
onebyone: true

就这么简单,发现 reboot 后,thin启动不起来 , 百思不得其解,

使用

>/etc/init.d/thin start

可以顺利启动

>service start thin

启动不了,提示找不到 thin,所以问题可能在这

于是google,最后找到了 rvm wrapper

我为我的项目使用了 rvm gemset , gemset名字为 huaianxinao

使用gemset

rvm @huaianxinao

生成wrapper

rvm wrapper ruby-1.9.3-p318@huaianxinao bootup thin

可以看到是生成了一个这样的可执行文件

/usr/local/rvm/bin/bootup_thin

于是把你的thin init.d 脚本的DAEMON修改为该路径

测试

>service thin start 

可以顺利启动,

>sudo reboot

thin 顺利自启动, OH YEAR O_O

最后看下 wrapper 原理,ls -l 看下 bootup_thin文件:

wxianfeng@SNDA-192-168-2-15:~$ ls -l /usr/local/rvm/bin/bootup_thin
lrwxrwxrwx 1 wxianfeng rvm 56 2012-04-21 17:29 /usr/local/rvm/bin/bootup_thin -> /usr/local/rvm/wrappers/ruby-1.9.2-p318@huaianxinao/thin

发现从gemset那ln -s 过来的,继续cat看下

wxianfeng@SNDA-192-168-2-15:~$ cat /usr/local/rvm/wrappers/ruby-1.9.2-p318@huaianxinao/thin
#!/usr/bin/env bash

if [[ -s "/usr/local/rvm/environments/ruby-1.9.2-p318@huaianxinao" ]]
then
  source "/usr/local/rvm/environments/ruby-1.9.2-p318@huaianxinao"
  exec thin "$@"
else
  echo "ERROR: Missing RVM environment file: '/usr/local/rvm/environments/ruby-1.9.2-p318@huaianxinao'" >&2
  exit 1
fi

发现source了这个文件 /usr/local/rvm/environments/ruby-1.9.2-p318@huaianxinao,cat 看下

wxianfeng@SNDA-192-168-2-15:~$ cat /usr/local/rvm/environments/ruby-1.9.2-p318@huaianxinao
export PATH ; PATH="/usr/local/rvm/gems/ruby-1.9.2-p318@huaianxinao/bin:/usr/local/rvm/gems/ruby-1.9.2-p318@global/bin:/usr/local/rvm/rubies/ruby-1.9.2-p318/bin:/usr/local/rvm/bin:$PATH"
export rvm_env_string ; rvm_env_string='ruby-1.9.2-p318@huaianxinao'
export rvm_path ; rvm_path='/usr/local/rvm'
export rvm_ruby_string ; rvm_ruby_string='ruby-1.9.2-p318'
export rvm_gemset_name ; rvm_gemset_name='huaianxinao'
export RUBY_VERSION ; RUBY_VERSION='ruby-1.9.2-p318'
export GEM_HOME ; GEM_HOME='/usr/local/rvm/gems/ruby-1.9.2-p318@huaianxinao'
export GEM_PATH ; GEM_PATH='/usr/local/rvm/gems/ruby-1.9.2-p318@huaianxinao:/usr/local/rvm/gems/ruby-1.9.2-p318@global'
export MY_RUBY_HOME ; MY_RUBY_HOME='/usr/local/rvm/rubies/ruby-1.9.2-p318'
export IRBRC ; IRBRC='/usr/local/rvm/rubies/ruby-1.9.2-p318/.irbrc'
unset MAGLEV_HOME
unset RBXOPT

发现设置了很多环境变量,所以找到问题了,你必须设置 rvm一系列的环境变量,才可以搞定!

SEE:
http://beginrescueend.com/integration/init-d/
http://stackoverflow.com/questions/3230404/rvm-and-thin-root-vs-local-user


capistrano 多机部署

Posted by wxianfeng Thu, 12 Apr 2012 03:39:00 GMT

核心使用 task 指令 实现多机部署

# encoding:utf-8
# >cap local deploy
# >cap remote deploy

set :application, "entos"
set :deploy_to, "/data/projects/entos"

set :scm, "git"
set :repository,  "git@114.255.155.167:entos.git"
set :branch, "master"
set :use_sudo, false
set :rails_env,"production"

task :remote do
  set :user, "entsea"
  set :deploy_via, :remote_cache
  set :copy_exclude, %w(external)
  server "114.255.155.166", :web, :app, :db, :primary => true
end

task :local do
  set :user, 'zzq'
  set :deploy_via, :remote_cache
  set :copy_exclude, %w(external)
  server '192.168.10.105', :web, :app, :db, :primary => true
end

namespace :deploy do
  task :start do; end
  task :stop do; end

  desc "Creating ln -s , example: database.yml"
  task :create_sync do
    run "ln -s #{shared_path}/config/database.yml #{current_path}/config/database.yml"
  end

  desc "Restarting unicorn"
  task :restart, :roles => :app, :except => { :no_release => true } do
    # run "/bin/sh restart_server.sh"
  end
end

after "deploy:symlink", "deploy:create_sync"

正则 ?: 非捕获组

Posted by wxianfeng Wed, 21 Mar 2012 03:03:00 GMT

今天一个同事 问我 正则 里 ?: 什么意思,记得 以前知道的 , 愣是 忘记了 ,查了下 是非捕获组的意思!

捕获组
()内的是分组,可以用 $1,$2…取值, 被存在了内存中, 留反向引用.
demo:

ruby-1.9.2-p290 :022 >   "abcabc".match(/(abc)/)
 => #<MatchData "abc" 1:"abc"> 
ruby-1.9.2-p290 :023 > $1
 => "abc" 

非捕获组
(?:) 内的不当作分组, 分组内内容,内存中没有.
demo:

ruby-1.9.2-p290 :024 > "abcabc".match(/(?:abc)/)
 => #<MatchData "abc"> 
ruby-1.9.2-p290 :025 > $1
 => nil 

那么这个有什么用呢, 可以节省内存

demo

ruby-1.9.2-p290 :033 > "hello" =~ /h(i|ello)/
 => 0 
ruby-1.9.2-p290 :033 > $1
 => "ello" 
ruby-1.9.2-p290 :034 > "hello" =~ /h(?:i|ello)/
 => 0 
ruby-1.9.2-p290 :035 > $1
=> nil

ruby string to class

Posted by wxianfeng Wed, 16 Nov 2011 20: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


北京 798 Ruby/Rails 活动

Posted by wxianfeng Fri, 29 Jul 2011 18: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 00: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 

ruby rake tips

Posted by wxianfeng Tue, 25 Jan 2011 17: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/