一个小技巧,在Ola Bini 的blog上看到的。
假设你想要这样一个类:
创建这个类的时候send一个block给它,然后在后面可以通过某个方法名来调用这个block。
class DoSomething
def initialize
(class << self; self; end).send :define_method, :call do
yield
end
end
end
d = DoSomething.new do puts "hello world"
end
d.call
d. ...
Engineering Puzzle
You have four colored cubes. Each side of each cube is a single color,
and there are four colors: blue (B), red (R), green (G) and yellow (Y)
Describing the six faces as front, back, left, right, top, bottom, the
cube colors are:
Front Back Left Right Top Bottom
1 R B ...
在ruby1.9中增加了External Iterators这中新的迭代类型,所有的Enumerable 都是External Iterators.而在ruby1.9之前的版本中的迭代都是internal iterator。
何为external iterator呢,其实我认为也就是一个生成器了:
iterator = 9.downto(1) # An enumerator as external iterator
begin # So we can use rescue below
print it ...
比如下面一个文件 people.txt
引用name,age,weight,height
"Smith, John", 35, 175, "5'10"
"Ford, Anne", 49, 142, "5'4"
"Taylor, Burt", 55, 173, "5'10"
"Zubrin, Candace", 23, 133, "5'6"
我们的目标是什么呢?我们的目标就是实现类似于Rails中的Builder模块所做的事情,假设我们第二行数据 对象为a,那么我们可以通过a.name,a.age等等来得到他所对应的值:
class DataRecord
def se ...
今天没事看blog的时候,看到一个小子实现了这个,不过他的程序写的那叫一个丑陋,实在是看不下去,就自己写了个.
原理很简单,那就是首先将要检测的方法重命名掉,然后动态定义一个相同的,这时他就会调用我们定义的这个方法,这时我们就可以检测参数的类型的,检测如果成功,在最后调用我们刚才重命名过的那个方法:
class Object
class << self
def check_type method_name,*arg_type
raise ArgumentError, "method_name is missing" unless new.res ...
其实这个类实现的功能很简单,那就是实现一个没有predefined 方法的类(除了__send__与__id__).自己也尝试着写了一个,思路什么和BlankSlate很接近,不过代码就丑陋多了。
当写这段代码之前,我们先要分析一下如何才能去掉predefined的方法,这里有三种predefined的方法。
1 Object类本身自带的一些实例方法.
2 打开Kernel模块,或者Object类,然后动态的加入的方法。
module Kernel
def name1
"bo"
end
end
class Object
def name2
"bo ...
首先,在ruby1.8中类变量是所有子类和父类共享的,可以看下面的代码:
class IntelligentLife
@@home_planet = nil
def self.home_planet
@@home_planet
end
def self.home_planet=(x)
@@home_planet = x
end
#...
end
class Terran < IntelligentLife
@@home_planet = "Earth"
end
class Martian < I ...
今天装Revactor库的时候,真把我郁闷了,没想到ubuntu源里面的ruby1.9装了之后,根本不能用gem来安装Revactor.最后google到了一篇文章,原来是要自己编译ruby1.9,然后才能正常使用gem.
源里面安装的ruby1.9,什么都没有,gem,rake什么的都没有,所以我们要自己编译,安装.
原文在这里:
http://blog.michaelgreenly.com/2007/12/multiple-ruby-version-on-ubuntu.html
假设你已经通过apt-get安装了ruby1.8,下来我们要安装ruby1.9
sudo apt-g ...
,自己本来想等啥时候有时间做个类似的东西呢,没想到已经有人做了,哈哈...
啥也不说了,准备最近研究研究这个代码...
地址在这里:
http://bus-scheme.rubyforge.org/
PS:这个竟然用的是git,哈哈,看来是被linus大叔给鼓动了..
1 rss 标准库
RSS 是基于xml的,因此你能简单的将它作为一个xml来进行解析.可是,事实上他有一个更高级别的专有的解析器来解析他.此外RSS的标准也很混乱。
他有很多不便,就是标准的版本的不兼容,RSS有0.9, 1.0, 和2.0的版本.RSS的版本,就像制造热狗,就是一些除非你一定要知道,否则你不想要知道的细节.
ruby有一个标准RSS库,它包含0.9,1.0和2.0版本标准.不同的版本之间尽可能做到了无缝处理.如果你没有指定版本,这个库他会自己尽可能地检测版本.
看下面的例子,这里我们是从http://marsdrive.com 得到feed:
require 'r ...
REXML 是一个完全用ruby写的processor ,他有多种api,其中两个经典的api是通过DOM-like 和SAX-like 来进行区分的。第一种是将整个文件读进内存,然后存储为一个分层的形式(也就是一棵树了).而第二种是"parse as you go",当你的文件很大,并且内存受到限制的时候,比较适合用这种。
看下面的book.xml:
引用<library shelf="Recent Acquisitions">
<section name="Ruby">
<book isbn="0672328844">
< ...
这些只是自己最近看web开发敏捷之道的时候(由于书中的版本是1.2,而我自己的是2.0),遇到的一些问题.
1 原来的render_{something}都被替换成了render :something
2 controller中的几个实例方法比如@params,@session,@flash,@request和@env都被相应的params,session,flash,request和env所替代.
3find_all和find_first被相应的find(:all)和find(:first)所取代.
4 paginate插件被移除掉了,推荐使用will_paginate,这个分页的 ...
1 得到所定义的实体的列表
ruby的反射api能够使我们在运行时检测类和对象。因此我们下面将会介绍Module, Class, 和Object中的定义的一些方法。
Module模块有一个constants 的方法,它将会返回系统中所有的常量名,包括类名和模块名。nesting 方法则是返回当前调用点上的嵌套的模块的列表.
list = Math.constants # ["E", "PI"]
Module#ancestors 返回指定的类或者模块的所有包含的类或者模块.
list = Array.ancestors
# [Array, Enumerable, Objec ...
1 动态的evaluate代码
全局的方法eval 编译并且执行一段包含ruby代码片断的字符串,这是一个很power的机制,因为它允许你建造在运行时
执行的代码。看下面的例子:
parameters = {}
ARGF.each do |line|
name, expr = line.split(/\s*=\s*/, 2)
parameters[name] = eval expr
end
假设输出是这样的:
引用a = 1
b = 2 + 3
c = `date`
然后你的parameters 应该是这样的{"a"=>1, "b"=>5, "c"=>"Mon ...
1 把代码像对象一样存储
当你想要以对象的形式存储一块代码的时候,ruby给了你几种方法。下面我们会介绍Proc 对象, Method 对象和 UnboundMethod 对象.
内置的Proc 类包装ruby block到一个对象.Proc对象,像一个blocks,是一个闭包而且保存了它定义时的上下文:
myproc = Proc.new { |a| puts "Param is #{a}" }
myproc.call(99) # Param is 99
当一个方法接受一个&的参数,然后这个方法紧跟着一个block被调用的时候,Proc 对象就会自动被创建:
...
1 发送一条消息给一个对象
当你调用一个方法时,你也就是发送了一条消息给一个对象,在ruby中我们能够在运行时决定那个方法被调用。send 方法就是做这个的,他接受一个symbol为参数.
举个简单的例子,假设我们要写一个排序,我们想要使用不同的域作为比较的key。虽然我们这时可以用block,可是如果使用send的话,我们能有一个更优美的写法:
class Person
attr_reader :name, :age, :height
def initialize(name, age, height)
@name, @age, @height = name, ...
1 理解allocate
在一些特殊的环境中,你可能需要不调用它的构造器(也就是initialize)来创建一个对象。也就是说你想要创建一个空的对象.例如,假设你有一个对象,它的状态完全的由它的存取方法所确定,因此如果你不是真的想要一个另外的状态的话,调用new方法是没必要的.此时我们能allocate方法.
class Person
attr_accessor :name, :age, :phone
def initialize(n,a,p)
@name, @age, @phone = n, a, p
end
def test
p "aaa ...
1 使用多个构造方法
在ruby中没有像c++或者ruby中的构造器,可是我们依然能够创建出类似的多个构造器:
class ColoredRectangle
def initialize(r, g, b, s1, s2)
@r, @g, @b, @s1, @s2 = r, g, b, s1, s2
end
def ColoredRectangle.white_rect(s1, s2)
new(0xff, 0xff, 0xff, s1, s2)
end
def ColoredRectangle.gray_rect(s1, s2)
...
这边都只是个大概,具体的要自己去看文档了.
1 连接SQLite:
require 'sqlite'
db = SQLite::Database.new("library.db")
db.execute("select title,author from books") do |row|
p row
end
db.close
2连接mysql:
require 'mysql'
m = Mysql.new("localhost","name","password","maillist")
r = m.query("SELECT * FROM ...
经常我们需要以一种更透明的方式来存储和得到数据.Marshal模块提供了简单的对象持久化,PStore 库建立在这项技术之上。dbm 库使用像hash一样并永久的存贮在磁盘上.
1简单的Marshaling
经常我们需要创建一个对象,然后为了以后的使用保存它.ruby对这种对象持久化(或者说是Marshaling)提供了基本的支持.Marshal 模块能够使程序员序列化和反序列化一个ruby对象.
# array of elements [composer, work, minutes]
works = [["Leonard Bernstein","Overture to Ca ...
1 检测文件是否存在及其大小
FileTest的 exist?方法可以检测一个文件是否存在:
flag = FileTest::exist?("LochNessMonster")
flag = FileTest::exists?("UFO")
# exists? is a synonym for exist?
如果我们想要知道文件是否有内容,可以使用File::Stat的zero? 方法:
flag = File.new("somefile").stat.zero?
这个将会返回true,这是因为在ruby中0也是true,nil才是false.
所以我们可以使用size?方法 ...
1 打开和关闭一个文件
类方法File.new 打开一个文件,并将它实例化为一个File对象,他的第一个参数是文件名.
可选的第二个参数叫做 mode string(这个也是从c得来的).他的意思是怎样打开一个文件(读,写或者其他的).默认是'r'(也就是读).
file1 = File.new("one") # Open for reading
file2 = File.new("two", "w") # Open for writing
另外一种new的形式是三个参数的,其中第二个参数是指定了这个文件的原始的权限(经常表示为一个八进制的数).第三个参数是一系列Ore ...
Enumerable 模块是一个很重要的模块,ruby中的很多类都有mix这个模块,比如array,hash等等。因此如果你想要自己定义一个collection,则不要继承一个存在的collection,而是应该mix Enumerable 模块。
数组是最常用,最有代表性的mix Enumerable模块的一个集合。因此下面的都会默认用数组来举例子
1 inject方法
先看一个很简单的例子:
nums = [3,5,7,9,11,13]
sum = nums.inject(0) {|x,n| x+n }
这个结果就是 将nums的元素一次累加起来付给x,然后最终返回x.而inj ...
1创建一个hash
就想创建一个数组一样,我们能够使用Hash的[]方法来创建一个hash:
puts a1 = Hash.[]("flat",3,"curved",2)
puts a2 = Hash.[]("flat"=>3,"curved"=>2)
puts b1 = Hash["flat",3,"curved",2]
puts b2 = Hash["flat"=>3,"curved"=>2]
puts c2 = {"flat"=>3,"curved"=>2}
相似的,我们还可以使用new来创建一个hash:
puts d = Hash.new # 创建一个 ...
1 创建和实例化一个数组
类方法[]能够创建一个数组,这里有3种方法使用[]来创建一个数组:
a = Array.[](1,2,3,4)
b = Array[1,2,3,4]
c = [1,2,3,4]
这里还有一个方法叫做new也可以创建一个数组,它可以接受0,1或者2个参数,第一个参数是数组的大小,第二个参数是数组中每一个元素的默认值。
d = Array.new # Create an empty array
e = Array.new(3) # [nil, nil, nil]
f = Array.new(3, "b ...
1 1个简单的数字区间我们能这样表示:
digits = 0..9
scale1 = 0..10
scale2 = 0...10
其中..包括结束点,...不包括结束点,也就是说digits和scale2的表示范围是一样的.
在ruby中,不只是数值可以用作区间,任何ruby对象都可以用作区间。可是并不是所有的表示都有意义或者有用。
接下来让我们来看看怎么操作区间:
2 开区间和闭区间
就像上面说的,..是闭区间,...是开区间:
r1 = 3..6 # closed
r2 = 3...6 # open
a1 = r1.to_a # [3,4,5, ...
1 symbols简介
在ruby中一个symbol就是一个Symbol类的实例,他的语法也就是简单的一个冒号后面跟着一个声明.
一个symbol就像一个字符串,可是它和字符串所不同的是每一个symbol都只有一个实例。我们举个例子:
array = ["foo", "foo", "foo", :foo, :foo, :foo]
在这个例子中字符串"foo"在内存里面被存储为3个不同的对象,而:foo则是被存储为一个对象,只不过是多个引用而已。
在ruby1.6之前的版本,一个symbol不是一个first-class 的对象,他是被传递给一个Fixnum ,然后再存储起来。在现在的 ...
1定积分的计算
我么可以使用Riemann sum来计算积分:
def integrate(x0, x1, dx=(x1-x0)/1000.0) #也就是求一个函数在x0到x1区间的积分
x = x0
sum = 0
loop do
y = yield(x)
sum += dx * y
x += dx
break if x > x1
end
sum
end
def f(x)
x**2
end
z = integrate(0.0,5.0) {|x| f(x) }
puts z, "\n" ...
1 处理复数
标准库complex 能使我们处理复数。一个复数的创建能使用Complex来构造:
require 'complex'
puts Complex(1,2) # 3+5i
方法im能够转换一个数字为虚数:
puts a = 3.im # 3i
puts b = 5 - 2.im # 5-2i
如果你想表示极坐标的话,可以使用polar方法:
puts z = Complex.polar(5,Math::PI/2.0) #第一个参数是半径,第二个参数是角度
Complex还提供了I这个常量,他就表示复数中的i:
puts z1 = Compl ...







评论排行榜