Ruby 小技巧之 $:

在一些gem里面经常会有这样一句代码:

1
$:.unshift File.expand_path('..', __FILE__)

这句话是干什么用的呢?

$: 就是ruby的一个全局变量,也叫$LOAD_PATH,功能就是java中的classpath,用来加载类库的,当你require某个文件时,ruby就会从这个变量的值去查找,找不到会报LoadError。这个值其实就是一个包含了类库绝对路径的数组。

__FILE__这个变量代表文件自己的文件名,在foo.rb中puts __FILE__,结果就是foo.rb。

File.expand_path可以把路径转换成绝对路径,假设有这样一个文件/Users/kenshin/foo.rb,里面有File.expand_path('..', __FILE__),返回的结果就是/Users/kenshin。

unshift是数组的一个方法,功能就是把指定的值加到数组的最前面,[3,4].unshift(1,2) => [1,2,3,4]

所以这段代码的意思就是把当前文件所在的目录加到ruby的loadpath的最前面,在require文件时,ruby就会先从当前目录下去查找了。

Ruby 的迭代器

ruby中针对集合(数组、哈希)的迭代器有 each map collect inject,下面将逐一介绍

1 each用法

each方法是最简单也最常用的,它会连续访问集合的所有元素然后传值给bloc执行,比如:

1
2
3
[1,2,3,4,5].each do |a|
  puts a
end

运行结果:

 1
 2
 3
 4
 5

2 reverse_each 用法:

对比each,从字面上理解reverse_each就是逆序迭代,例如

1
2
a = [1,2,3]
a.reverse_each { |v| puts v }

运行结果

3
2
1

a.reverse_each 和 a.reverse.each 有什么区别呢? 功能是一样的,但是效率不同, reverse_each的效率更高

1
2
3
4
irb(main):001:0> now =Time.now; Array.new(30000000) {rand}.reverse.each {|x|x*2}; Time.now-now
=> 15.705195
irb(main):002:0> now =Time.now; Array.new(30000000) {rand}.reverse_each {|x|x*2}; Time.now-now
=> 12.956333

3 map用法

map也很常用,它从集合中获得各个元素传递给block,block返回的结果生成新的集合,比如:

[1,2,3,4,5].map{ |a| a + 1 } -> [2, 3, 4, 5, 6]

再比如:

1
2
users = User.where(:age => 20)
users.map{|user| user.name } -> ['zhangsan','lisi','wangwu']

这个例子可以简写成: users.map(&:name) ,其运行结果也是一样的

Continue reading →

Reactor 模式

Reactor 设计模式(也叫反应器模式,或者应答者模式)是一种基于事件驱动的设计模式,这种模式像是一个女仆或者服务员,随时等待你的召唤。

高并发的场景经常使用Reactor模式取代常用的多线程处理模式,以节省系统资源,提高系统的吞吐量。

说到这里到底什么是Reactor模式,什么又是多线程模式呢?我们举个栗子:

假设有这么一个场景:你去餐厅吃饭,首先要有服务员将菜单拿给你,你选好以后,服务员帮你完成点餐。

第一种情况: 每有一位乘客光临,就分配一个服务员帮助点餐。

第二种情况: 当乘客来到来以后,服务员会给你菜单,你先点菜。这时服务员去服务其他客人,当你选好以后招呼一下‘服务员’,会有服务员过来帮你点餐。

每个客人好比是一个请求事件,餐厅的服务员好比请求的处理。

第一种情况就是典型的多线程模式,每一个事件到来,都会分配一个线程来处理请求。无疑这样的服务是最好的,每个客人都会觉得自己是vip,于是这家店的口碑越来越好,越来越多的客人来这里用餐,很快老板就发现忙不过来了,多请服务员吧,占地方不说还要多出工钱,成本太大了。

显然第二种情况更好一点,较少的资源服务了较多的客人,这就是Reactor模式,用单线程来干多线程的事,进程和线程的开销是很大的,内存占用高不说,上下文之间的切换也是很慢的。

Reactor模式主要是提高系统的吞吐量,在有限的资源下处理更多的事情。

利用Reactor模式的框架:

Node.js Gevent、Twisted、Tornado(Python) EventMachine、Rev(Ruby)

Rails 代理方法 Delegate

通过delegate方法,在Foo对象中可以直接引用Greeter对象的方法:

Ruby代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Greeter < ActiveRecord::Base
  def hello
    "hello"
  end

  def goodbye
    "goodbye"
  end
end

class Foo < ActiveRecord::Base
  belongs_to :greeter
  delegate :hello, :to => :greeter
end

Foo.new.hello   # => "hello"
Foo.new.goodbye # => NoMethodError: undefined method `goodbye' for #<Foo:0x1af30c>

Multiple delegates to the same target are allowed:

Ruby代码:
1
2
3
4
5
6
7
class Foo < ActiveRecord::Base
  belongs_to :greeter
  delegate :hello, :goodbye, :to => :greeter
end

Foo.new.hello   # => "hello"
Foo.new.goodbye # => "goodbye"

delegate方法首先检查传入的参数,正确参数形式为:method1, :method2, …, :methodN, :to => klass[, :prefix => prefix]

delegate要求参数的最后必须是一个Hash, :to表示需要代理的类,:prefix表示代理的方法是否要加前缀, 如果:prefix => true,则代理的方法名为klass_method1, klass_method2, …, klass_methodN,

Ruby代码:
1
2
3
4
5
6
class Foo < ActiveRecord::Base
 delegate :hello, :goodbye, :to => :greeter, :prefix => true
end

Foo.new.greeter_hello   # => "hello"  
Foo.new.greeter_goodbye # => "goodbye"  

如果:prefix => prefix (prefix为string),则代理的方法名为prefix_method1, prefix_method2, …, prefix_methodN。

Ruby代码:
1
2
3
4
5
6
class Foo < ActiveRecord::Base
  delegate :hello, :goodbye, :to => :greeter, :prefix => :foo
end

Foo.new.foo_hello   # => "hello"  
Foo.new.foo_goodbye # => "goodbye"  

Controller 中使用 Helper

helper方法默认只能在view层调用(比如strip_tags方法)。如果想要在controller或model中使用,有两中方法:

方法一:

Ruby代码:
1
2
3
4
5
class PostsController < ApplicationController
  def create
    ActionController::Base.helpers.strip_tags('string')
  end
end

方法二:

用代理delegate

Ruby代码:
1
2
3
4
5
6
7
class PostsController < ApplicationController
  delegate "strip_tags", :to => "ActionController::Base.helpers"
  def create
    strip_tags("html...")
    ...
  end
end

Rails 小坑

我在一个controller中定义了一个action,在这个action的最后:

Ruby代码:
1
2
3
4
redirect_to :action => 'show', :id => params[:term_id] , :data_type => params[:data_type], :specialty => params[:specialty],
                :norm_series => params[:norm_series], :range_from => params[:range_from], :range_to => params[:range_to],
                :top_type => params[:top_type], :sub_type => params[:sub_type], :review_type => params[:review_type],
                :status => params[:status], :page_size => params[:page_size] || 20, :page => params[:page] || 1

当这个页面执行完以后,没有转到‘show’页面,却进入了一个空白的页面,这个页面只有一句话:

You are being redirected.

点击 ‘redirected’ 以后,页面才跳转到’show’ 页面,百思不得其姐。

最后通过查资料和自己思考终于知道原因了,关键在于后面的堆参数,其中有个 status 变量。哈哈~

说到这里你应该能猜到原因了吧。

Rails 命令行工具

rails 命令行工具

整理一些不常用的但是很有用的命令行工具:

1 rails c –sandbox

在沙盒模式下启动rails命令行,再此所做的对数据的修改都会会滚。

2 rails runner “puts User.first.id”

在rails环境下执行ruby代码,无需启动应用服务。

3 rails dbconsole

启动数据库的命令行,无需数据用户名密码,支持MySQL, PostgreSQL, SQLite and SQLite3.

4 rails destroy

回滚 rails g 对项目的改变。

5 rake -T

查看所有的rake任务。

6 rake about

查看rails应用的环境,包括ruby版本,rails版本等。

7 rake notes

查看项目中的 TODO(待完成)、FIXME(待修复)、OPTIMIZE(待优化)

8 rails g

用于生成脚手架、控制器、模型、数据库迁移任务等。 如果加一个 -p 参数,只输出生成的文件列表,而不是真的创建文件

参考资料:

http://guides.ruby-china.org/command_line.html[http://guides.ruby-china.org/command_line.html]

Ubuntu 读写 Windows 文件

前提:windows系统电脑和ubuntu在同一个局域网内。

在图形模式下:

  1. 打开任意一个文件浏览器

  2. 输入 Ctrl + l

  3. 输入windows电脑地址:smb://192.168.71.34

  4. 在弹出界面输入 windows 电脑的用户名、密码、工作组等信息

  5. 搞定~!

在命令行模式下: 命令:mount //192.168.10.56/share -o user=DOMIAN\\user,pass=passwd /mnt

注意有两点

(1)domain这里是域名,并且要大写

(2)这里有两个\,其中第一个是转义符,第二个是\

Linux 查看文件夹大小

du -sh 查看当前文件夹大小

du -sh * | sort -n 统计当前文件夹(目录)大小,并按文件大小排序

du -sk filename 查看指定文件大小

Linux Top 命令

top命令经常用来监控linux的系统状况,比如cpu、内存的使用.

执行top命令,系统显示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
top - 19:40:49 up 11:00,  2 users,  load average: 0.24, 0.42, 0.54
Tasks: 192 total,   1 running, 190 sleeping,   0 stopped,   1 zombie
Cpu(s):  2.5%us,  1.0%sy,  0.0%ni, 96.4%id,  0.0%wa,  0.0%hi,  0.1%si,  0.0%st
Mem:   3923984k total,  2716120k used,  1207864k free,   705260k buffers
Swap:   262140k total,    69596k used,   192544k free,  1385228k cached

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
1168 root      20   0 90320  22m 7676 S    4  0.6  15:17.95 Xorg
1947 ivan      20   0  388m  70m  22m S    4  1.8  16:11.03 compiz         
2116 ivan      20   0  115m  24m  13m S    1  0.6   0:37.49 python         
7346 ivan      20   0  142m  22m  14m S    1  0.6   0:05.42 gnome-terminal 
2031 ivan      20   0  106m  25m  12m S    1  0.7   3:50.68 unity-panel-ser
2113 ivan      20   0 47556 4184 2520 S    1  0.1   0:45.45 ibus-daemon    
7695 ivan      20   0  413m  99m  42m S    1  2.6   0:12.53 chrome         
7713 ivan      20   0  389m  62m  15m S    1  1.6   0:09.25 chrome         
1822 root      20   0 88528 1712 1484 S    0  0.0   2:19.14 mongod         
1919 ivan      20   0  6968 3108  620 S    0  0.1   1:23.65 dbus-daemon    
1932 ivan      20   0  238m  13m 9884 S    0  0.3   0:25.07 gnome-settings-
2033 ivan      20   0 71728 8896 3336 S    0  0.2   0:30.65 hud-service    
2104 ivan      20   0 42080 5500 4460 S    0  0.1   0:01.97 ubuntu-geoip-pr
   1 root      20   0  3664 1796 1204 S    0  0.0   0:00.69 init           
   2 root      20   0     0    0    0 S    0  0.0   0:00.00 kthreadd       
   3 root      20   0     0    0    0 S    0  0.0   0:03.90 ksoftirqd/0    
   6 root      RT   0     0    0    0 S    0  0.0   0:00.21 migration/0    
   7 root      RT   0     0    0    0 S    0  0.0   0:00.15 watchdog/0     
  20 root       0 -20     0    0    0 S    0  0.0   0:00.00 cpuset         
  21 root       0 -20     0    0    0 S    0  0.0   0:00.00 khelper        
  22 root      20   0     0    0    0 S    0  0.0   0:00.00 kdevtmpfs      
  23 root       0 -20     0    0    0 S    0  0.0   0:00.00 netns          
  25 root      20   0     0    0    0 S    0  0.0   0:00.13 sync_supers    
  26 root      20   0     0    0    0 S    0  0.0   0:00.00 bdi-default    
  27 root       0 -20     0    0    0 S    0  0.0   0:00.00 kintegrityd    

第一行:

19:40:49表明当前系统时间; up 11:00 表明系统持续运行11个小时;2 users:目前两个登录用户; load average: 0.24, 0.42, 0.5 :表明最近的 1、5、15 分钟系统的负载情况

第二行:进程状态

Tasks: 192 total, 1 running, 190 sleeping, 0 stopped, 1 zombie :目前进程总数192,其中1个在运行中,190个休眠中,1个僵死;

第三行: CPU使用情况

2.5%us: 当前用户CPU占用百分比 1.0%sy: 系统内核CPU占用百分比 0.0%ni: 优先继承的CPU占用百分比 96.4%id:空闲CPU占用百分比 0.0%wa: IO等待进程CPU占用百分比 0.0%hi: 硬中断CPU占用百分比 0.1%si: 软中断CPU占用百分比 0.0%st

第四行:内存使用情况

3923984k total: 物理内存总量(4G) 2716120k used: 已经使用2.7G 1207864k free: 空闲物理内存(1.2G) 705260k buffers:缓存内存量(700兆)

第五行:swap交换分区

262140k total: 总共260兆 69596k used: 已经使用70兆 192544k free: 剩余190兆 1385228k cached:缓冲的交换区1.3G

第六行: 空行

PID 进程id USER 进程所有者 PR 进程优先级 NI nice值。负值表示高优先级,正值表示低优先级 VIRT 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES RES 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA SHR 共享内存大小,单位kb S 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程 %CPU %MEM TIME+
COMMAND