阿当的博客











{十二月 14, 2009}   rails学习笔记(2)

1)rails自动生成的目录中,lib目录和vendor目录分别用于存放你自己编写的组件或者第三方提供的组件,它们需要被你的应用程序用到,但又不专属于你的项目。log目录下存放的是日志文件,日志文件会针对开发环境,测试环境和生产环境分别记录。config目录是用来设置rails的配置的,其中包括用于配置服务器链接的yml文件和运行时环境配置文件等。运行时环境配置可以针对三个环境分别进行设置,公共的部分在config根目录下的environment.rb文件中设置,而针对某个环境的设置,则在config/environments/目录下的development.rb、production.rb、test.rb中进行个性设置。

2)在启动web服务器时,可以通过加上-e选项,指定启动时选用哪个环境

==================================

ruby script/server -e development | test | production

==================================

3)rails里强调“惯例重用配置”,从数据库中的表,到控制器,到模型,再到视图,命名是有关联的!文件的存放路径也是有关联的。我们在命名和存放文件时需要遵守这种惯例。一旦我们遵守了这种惯例这四者之间的映射都是rails自动替我们去完成的,这也是rails为何能“敏捷”的重要原因。

4)在编写普通ruby代码时,如果我们想要使用另一个文件中的类和模块,需要先require它们,但在rails中编程,因为rails有命名约定,所以可以不用require它们就直接使用,rails会根据命名约定(也包括路径约定),去自动加载该文件!不过,也有例外的时候,如果被引用的类要在session中保存,自动加载就会失效,但即便如此,我们也仍然不需要require,我们只需要在类里加上一句 model :类文件名(注,小字加下划线分隔)。

==================================

class StroeController < ApplicationController

model :line_item               #rails会去加载line_item.rb文件,其中包含LineItem类。

==================================

5)控制器的路径默认是存放在app/controllers根目录下的,但如果我们需要在根目录下再组织一下控制器的路径,那么可以将控制器的声明位于ruby模块之下。例如,我们要将book_controller.rb文件放置于admin目录下,也就是app/controllers/admin/book_controller.rb,那么,我们就应该这样声明:

==================================

class Admin::BookController < ApplicationController

..

end

==================================

幸运的是,rails的生成器很智能,你可以直接使用

==================================

ruby script/generate controller Admin::Book action1 action2

==================================

来生成你需要的路径。

6) rails用ActiveRecord来处理对象-关系映射(ORM)。数据库中的一张表对应着模型中的一个类,表名是小写的,多单词用下划线分隔,而且是复数形式。对应的类名是单词首字母大写来进行分隔的,而且是单数形式。表中的字段直接映射成类的属性,除此之外,我们还可以给类再另外添加一些属性。表名和类名是通过命名惯例去自动对应的,(rails对ruby的字符串类进行了扩展,让它直接支持单复数之间的转变,例如 puts “cat”.pluralize    #=>cats         puts “cats”.singularize #=>cat),仅管pluralize和singularize方法已经很智能了,能处理child和children这样的单复数转换,但它仍然还是有缺陷,例如sheep会对应到sheeps。我们可以在模型类中,cefpset_table_name去显示地指明对应的表,而不使用缺省的惯例。

==================================

class Sheep < ActiveRecord::Base

    set_table_name “sheep”

end

==================================

7)ActiveRecord从表中取出值,变成类的对象时,会自动将数据库中的类型转换成ruby支持类型,例如数据库字段是timestamp类型的,就会返回Time对象。如果你希望得到一个属性的原始值,可以在属性名称后面加上_before_type_cast。

==================================

account.balance_before_type_cast

==================================

如果在模型内部,可以使用私有方法read_attribute()和write_attribute()。

8)布尔型的数据在转换的时候会有些麻烦,有些数据库是不支持布尔型的,所以我们在工作中,可以使用0,1这样的数字来代表布尔值的真假,而ruby中只有false和nil为假,0其实是为真的。所以在数据库映射到类时,我们要判断某个属性的真假时,记得要加一个?号,这个是rails为解决布尔型问题而设置的。

==================================

# 错误写法

if user.superuser

    doSomeThing

end

 

# 正确写法

if user.superuser?

    doSomeThing

end

==================================

9) 在编程时,可以某个属性对应的是一个对象,而不是一个简单类型的数据。在类和表的映射的时候,这种复杂类型的属性也是可以直接保存到表中的一个字段的,这个字段必须是text类型的,属性会以字符串的形式存进数据据。而从数据库中映射到类时,需要在类中加以声明,某个字段是个对象,不是普通字符串。声明的方法是serialize()。复杂类型包括对象,数组,hash等等。

==================================

class Purchase < ActiveRecord::Base

   serialize :last_five

    …

end

==================================

10)主键。一般来说,rails都会用id作为每张表的主键,但表并不是由我们自己来建的,可能表会用别的字段作为主键。我们可以用set_primary_key来显示地指定主键字段。

==================================

class BadBook < ActiveRecord::Base

    set_primary_key “isbn”

end

==================================

但需要注意的是,既然指定主键为其它字段,但在访问时,仍然可以通过名为id的属性来设置主键值,也就是说,只要使用ActiveRecord,主键字段在对象中的属性名称就永远都是id。



{十二月 02, 2009}   rails学习笔记(1)

1) 在windows系统上安装rails很简单,首先需要安装ruby,完整安装,然后先在命令行输入gem –version,如果显示出版本号,就可以直接使用RubyGems来安装rails。直接在命令行输入 gem install rails –include-dependencies就可以自动完成安装了。需要注意的是,在windows系统上配置ror环境,还会出现一些奇怪的问题,具体安装过程推荐一篇博客:http://hi.baidu.com/haoweiren1234/blog/item/1d84b53875b8ea2cb9998f79.html,博主讲解得非常清楚。

2) ruby和其它服务器端语言一样,可以运行动态脚本,格式是<% %>。如果想输出显示,可以使用<%= %>。ruby的服务器使用的是WEBrick,不是appache,不是IIS,不是tomcat哦。

3)用rails新建一个项目很简单,在命令行输入 rails xxx,xxx就是项目的根目录文件夹名。然后rails会为你自动创建好目录结构,并提供好部分代码。rails提倡的敏捷开发,很大意义上依靠于这种带有“强制性”的自动操作。rails会为你建好目录,搭好框架,我们需要做的,只是填充框架里的内容。不用置疑rails自动搭建的框架是否优秀,是否弹性十足,是否可维护性良好。rails的敏捷开发目标,目的就是为了搭一个最优势的框架。

4)新建项目之后,在命令行输入 ruby script/server,运行rails自动为我们生成的代码中的server脚本,就可以启动WEBrick服务器了。



{十二月 02, 2009}   ruby学习笔记(6)

String 类

1)单引号和双引号。 单引号不会对里面的字符进行转义,类似于”\n”这样的转义会直接输出,也不能包含表达式。双引号则可以包含转议字符,也能包含表达式,表达式的格式为 #{xxxx}。需要注意的是,如果单引号里的字符串也包含单引号,还是要用“\’”进行转义的,这个转义是支持的。

=======================

a = “abc”

b = “1\n2\n3\n#{a}”

c = ‘1\n2\n3\n#{a}’

puts b          #=> 1   2   3   abc

puts c          #=>    1\n2\n3\n#{abc}

=======================

2) 新建字符串。

       <1> 直接使用 “”和”生成字符串。

        <2> 使用String.new()生成字符串。

       <3> 使用%Q和%q。 如果字符串中包括”"或”时,不想使用\”和\’频繁转义,可以使用%Q和%q来生成字符串。其中%Q相当于”,%q相当于’。和%w一样,分界符可以用<> @@之类的。

=======================

%Q(1\n2\n3\n#{a}”5678″‘9012′)

%q<1\n2\n3\n#{a}’5678′”9012″>

=======================

         <4> 如果是多行文本,可以使用<<”xxx” 或 <<-”xxx”来实现多行。一般xxx多使用EOB或EOF,表示end of black和end of file。注意,如果是xxx可以用单引号或双引号引起来,分别代表单引和双引,也可以不带引号,默认代表双引。注意<<和xxx之间要连在一起,不要有空格。

======================

a = 123

s = <<-”EOB”

i : abc

j : #{a}

adang is me

EOB

print s                     #=> i : abc   

                                       j : 123

                                        adang is me

======================

3) 字符串的长度。 字符串的长度可以用str.size或者str.length来获得。如果是英文字符,那么可以正常返回字符个数,但如果是非英文字符,比如说是中文字符,size返回的值就不正确了。因为ruby中返回的是字节数,不是字符数,这点和js不同。如果是中文,跟编码格式有关,如果是utf-8编码,那么一个中文占用三个字节,如果是ANSI编码,那么一个中文占用两个字节。为了解决这个问题,可以借助于正则表达式,换个思路获得字符串的字符长度。例如utf-8编码的,用str.split(//u).length,ANSI编码的,用str.split(//e).length。

=======================

utf-8编码

a = “我是个中文abc”              

puts a.size                               #=> 18      (5X3+3 = 18)

puts a.split(//u).length             #=> 8         (5+3 = 8)

ANSI编码

a = “我是个中文abc”              

puts a.size                               #=> 13      (5X2+3 = 13)

puts a.split(//e).length             #=> 8         (5+3 = 8)

=======================

4) empty?    ruby中字符串提供了empty?方法判断是否为空。注意,如果有空格或者tab,都不算为空的。

=======================

a = “”

p a.empty?               #=> true

a = ” ”

p a.empty?               #=> false

=======================

5) split和unpack。 ruby中分割字符串有两种方法,一种是split,按特定字符分隔,另一种是unpack,按“字节”数分隔。unpack的参数格式是aXaX,“X”表示要截取的字节数。需要注意提,如果X+X的字符数不够整个字符串长度的话,字符串后面的字符就没了,如果超过总长度的话,会按最大数来截取,如果不确定最后一节的长度,可以使用a*来截取至结尾处的部分。

=======================

a = “1:2:3:4:5:6″

p a.split(“:”)         #=>["1","2","3","4","5","6"]

p a.unpack(“a2a3″)    #=>["1:","2:3"]

p a.unpack(“a2a30″) #=>["1:","2:3:4:5:6"]

p a.unpack(“a2a3a*”) #=>["1:","2:3","4:5:6"]

=======================

6) +,<<,和concat。 ruby中字符串的连接有三个方式。用+号可以新建一个字符串,用<<和concat可以修改原字串的值(不新建字符串)。因为<<和concat是修改址的方法,影响会比较大,切忌不要乱用。

=======================

a = “123″

b = “456″

p a + b      #=> “123456″

p a            #=> “123″

 

a = “123″

b = “456″

a << b     

p a            #=> “123″

 

a = “123″

b = “456″

a.concat(b)     

p a            #=> “123456″

=======================

7) chomp! 。 删除行尾换行符。 以gets等方法从标准输入读入字符串时,行尾会接着换行符,但实际在处理字符串时,换行符经常很碍事,因此,加上chomp!几乎是一种固定写法。

=======================

a = “123\n”

p a.size           #=>4

a.chomp!

p a.size           #=>3

 

while line = gets

    line.chomp!

     ..

end

=======================

8) chop和chop!。 用于删除字符串的最后一个字符。



{十一月 27, 2009}   ruby学习笔记(5)

Array 类

1)新建数组。 ruby中新建数组有多种方法。

    <1> 使用[],类似于js。

================================

a = [1,2,3]

p a         #=> [1,2,3]

================================

      <2> 使用Array.new。

================================

a = Array.new

p a        #=> []

a = Array.new(5)

p a        #=> [nil,nil,nil,nil,nil]

a = Array.new(5,0)

p a        #=> [0,0,0,0,0]

================================

   <3> 使用%w。 %w方法很奇怪,后面接的可以直接是字符串,而不必带”号。通常情况下,可以选用()做为参数的边界符,如果字符串本身包含()这样的字符,为免造成影响,还可以使用<> || !! @@ AA这样的来做边界符。%w方法会以空格为分隔,将字符拆分成数组。

================================

a = %w(abc 123 def 456 ghi)

p a   #=> ["abc","123","def","456","ghi"]

a = %w<(abc) 1(23 g()h>

p a #=> ["(abc)",“1(23”,"g()h"]

================================

    <4>其它对象的to_a方法。 比如说hash对象就可以通过to_a转换成数组。

================================

h = {“name” => “adang”,”sex” => “male”}

a = h.to_a

p a           #=>[["name","adang"],["sex","male"]]

================================

        <5>字符串的split方法。

================================

s = “ab-123-cd-45″

a = s.split(“-”)

p a         #=>["ab","123","cd","45"]

================================

2) 数组的索引。

     <1> a[n]

      这个用法和别的语言没啥区别,唯一奇怪的是n可以为负值,表示倒数。另外,a.slice(n)和a.at(n)效果和a[n]相同。

================================

a = ["a","b","c","d"]

p a[0]   #=> a

p a[-2] #=> c

p a.slice(-2) #=> c

p a.at(-2) #=> c

================================

    <2> a[n..m]

     会将a[n]到a[m]之间的范围建立出新的数组返回。a.slice(n..m)和a[n..m]效果相同。

================================

a = ["a","b","c","d"]

p a[1..3]                    #=> ["b","c","d"]

p a[1..6]                    #=> ["b","c","d"]

p a.slice(1..3)            #=> ["b","c","d"]

p a[a]                        #=> ["a","b","c","d"]

================================

       <3> a[n,len]

       从a[n]处开始获取len个元素,建立新数组并返回。a.slice(n,len)和a[n,len]效果相同。

================================

a = ["a","b","c","d"]

p a[1,2]                  #=>["b","c"]

p a[1,6]                   #=>["b","c","d"]

p a.slice(1,2)          #=>["b","c"]

p a                         #=>["a","b","c","d"]

================================

         <4> a.values_at(n1,n2,…)

         a[n..m],a[n,len]方法新建的数组都只能是连续位置上元素,a.values_at方法可以返回不连续的索引组成的新数组。

================================

a = ["a","b","c","d"]

p a.values_at(1,3,0)        #=> ["b","d","a"]

p a                                   #=> ["a","b","c",“d”]

================================    

3) 改写数组。a[n],a[n..m],a[n,len]不仅可以读数据,还能写数据。注a.at,at.slice方法都只能读,不能写,只有a[]可以写。

================================

a = ["a","b","c","d","e","f","g"]
a[1..3] = ["B","C","D"]
a[4,2] = [1,2]
p a                  #=> ["a","B","C","D",1,2,"g"]

================================

4) 插入元素。 ruby中插入数据原理和js里一样。js中是通过splice方法先删几个元素,再添几个元素,ruby中也是如此。

================================

a = ["a","b","c"]

a[2,0] = [1,2]

p a    #=> ["a","b",1,2,"c"]

 

a = ["a","b",“c”]

a[1,1] = [1,2,3]

p a     #=> ["a",1,2,3,"b","c"]

 

a = ["a","b","c"]

a[1..2] = [1,2,3]

p a     #=> ["a",1,2,3]

================================

5) 交集、并集和差集。   ruby中数组还可以进行交集和并集的计算,分别使用 & 和 | 作为运算符。

================================

a = ["a","b","c","d"]

b = ["b","e","a"]

p a & b   #=> ["a","b"]

p a | b     #=> ["a","b","c",“d”,"e"]

p a         #=> ["a","b","c","d"]

================================

对数组直接使用 + – 运算符,可以分别得到数组连接的效果和差集的效果。

================================

a = ["a","b","c","d"]

b = ["b","e","a"]

p a – b    #=> ["c","d"]                                 (a有,但b没有的元素)

p   a + b   #=> ["a","b","c","d","b","e","a"]        (a和b简单地叠加)

p   a | b     #=> ["a","b","c","d","e"]                   (a和b的并集,重复元素去除)

================================

6)数组的队列性。 和js一样,ruby中的数据也有push,pop,unshift,shift方法,此外a << 赞同于a.push。

================================

a = ["a","b","c"]

a.unshift(1)

a << 2

a.push(3)

p a                         #=> [1,"a","b","c",2,3]

p a.shift                 #=> 1

p a                         #=> [“a”,"b","c",2,3]

p a.pop                 #=> 3

p a                         #=> ["a","b","c",2]                

================================

7) a.concat和 + 。    在js中数组是不能直接相加的,如果需要组合两个数组,是用a.concat(b)来实现的,但js中a.concat(b)是会返回一个新数组的,还可以利用这一点轻松复制一个复杂类型的数组。但ruby中concat是具有破坏性的,会影响到a。如果想不影响到a,可以使用+号。

================================

a = ["a","b","c"]

b = [1,2,3]

c = a + b

p c                                   #=>["a","b","c",1,2,3]

p a                                  #=>["a","b","c"]

c = a.concat(b)

p c                                    #=>["a","b","c",1,2,3]

p a                                   #=>["a","b","c",1,2,3]

================================

8)a.compact。 a.compact可以从数组中删除nil元素。有compcat和compact!之分。

================================

a = [nil,"a",nil,"b","c",nil]

a.compact!

p a            #=> ["a","b","c"]

================================

9)a.uniq。 a.uniq可以删除数组中的重复元素。有a.uniq和a.uniq!之分。

================================

a = [1,2,3,4,3,2,1]

a.uniq!

p a           #=> [1,2,3,4]

================================

10) a.delete(x)、a.delete_at(n)、a.delete_if{|item| …}

a.delete(x)可以直接从数组中删除指定元素(为啥js中没有这么好用的方法?T_T )。

a.delete_at(n)删除指定索引的元素(js的splice方法去死吧 T_T)。

a.delete_if{|item| …} 遍历数组元素,如果区块返回结果为真,则删除。 (for循环去死吧 T_T)。

================================

a = [1,2,3,2,4,nil]

a.delete(2)

p a             #=> [1,3,4,nil]

a = [1,2,3,2,4,nil]

a.delete_at(2)

p a             #=> [1,2,2,4,nil]

a = [1,2,3,2,4,nil]

a.delete_if{|item| item > 2 if item}

p a             #=> [1,2,2,nil]

================================

11) a.slice!()。 前面说过a.slice的效果等同于a[],包括a.slice(n),a.slice(n..m),a.slice(n,len)。slice方法还有slice!的形式,slice!方法的返回值相同,但会从数组中删除掉返回值。

================================

a = [1,2,3,4,5,6]

p a.slice!(1)       #=> 2

p a                     #=> [1,3,4,5,6]

p a.slice!(2..3)    #=> [4,5]

p a                    #=> [1,3,6]

p a.slice!(1,1)     #=> [3]

p a                      #=> [1,6]   

================================

12) a.collect和a.map。 如果需要让数组中所有元素统一变化,再也不用for()去循环,再赋值这么麻烦了,a.collect和a.map都可以返回让数组中的值进行处理之后,将返回的结果组成新数组。a.collect和a.map效果相同,且都有!的形式。

================================

a = [1,2,3]

a.collect!{|item| item * 2}

p a              #=> [2,4,6]

a.map!{|item| item * 3}

p a              #=> [6,12,18]

================================

13) a.fill。 a.fill可以将数组a的元素改写为指定的参数。但我a[n..m]=和a[n,len]=不同的是,a.fill只能将指定范围内的元素修改成一种参数(只有一种)。a.fill有a.fill(value),a.fill(value,begin),a.fill(value,begin,end),a.fill(value,n..m)几种不同的方式。

================================

a = [1,2,3,4,5,6]

a.fill(8)

p a         #=> [8,8,8,8,8,8]

a = [1,2,3,4,5,6]

a.fill(8,3)

p a         #=> [1,2,3,8,8,8]

a = [1,2,3,4,5,6]

a.fill(8,3,2)

p a         #=> [1,2,3,8,8,6]

a = [1,2,3,4,5,6]

a.fill(8,2..4)

p a         #=> [1,2,8,8,8,6]

================================

14)a.flatten。 将数组扁平化,多层数组可以变成一个单层的数组。有a.flatten和a.flatten!之分.

================================

a = [1,[2,3],[[4,5],6,[7,[8,9]]]]

a.flatten!

p a          #=> [1,2,3,4,5,6,7,8,9]

================================

15)a.reverse。 逆转数组,有a.reverse和a.reverse!之分。

================================

a = [1,2,3]

a.reverse!

p a      #=> [3,2,1]

================================

16)sort和sort_by。 sort对数组排序,对应的还有sort!方法。另外ruby还提供sort_by方法,sort_by返回新数组,没有对应的sort_by!

=================================

a = [2,4,3,5,1]

a.sort!

p a                  #=> [1,2,3,4,5]

b = a.sort_by{|i| -i}

p b                   #=> [5,4,3,2,1]

p a                  #=> [1,2,3,4,5]

=================================

17) each和each_width_index。 数组遍历最常用的做法是使用each方法,但each方法只会返回一个返回值,只有元素,没有索引,如果需要索引的话,可以使用each_with_index方法。

=================================

a = [1,2,3]
a.each{|i| print i,”\n”}
a.each_with_index{|i,n| print n,” : “,i,”\n”}

=================================



{十一月 27, 2009}   ruby学习笔记(4)

Numeric类

1) 整型和整型相加结果为整形,整形和浮点型相加,结果为浮点型。

================================

p 1+1            #=>2

p 1+1.0         #=>2.0

p 3 * 2.0       #=>6.0

================================

2) divmod。 除了+ – * / %之外,ruby中数值类型还有divmod方法,它也是除的运算符,只是返回值是数组的形式,第一项是商,第二项是余数。

================================

p 16.divmod(5)           #=> [3,1]

================================

3) Math模块和round方法。 ruby提供了Math模块,但和一般语言不同的是,round、ceil和floor方法并不是从属于Math模块的,而是直接绑定在数值类上的。Math模块提供的方法有sin、cos、tan、asin、acos、atan、exp、log、log10和sqrt。数值类型的对象转换可以用 to_f、to_i方法。浮点型转整型会直接去掉小数点后的值。字符串调to_i方法相当于js中的parseInt方法。

================================

f = 4

p Math.sqrt(f)           #=> 2

include Math

p sqrt(f)                   #=> 2

 

p   10.to_f                       #=> 10.0

p   10.8.to_i                   #=> 10

p    “123″.to_i                  #=> 123

p    “123abc”.to_i            #=> 123

p    “abc123″.to_i           #=> 0       (不是nil哦)

p    1.2.round                 #=> 1

p     1.2.floor                 #=> 1

p     1.2.ceil                    #=> 2

================================

3) 循环。 数值类型可以直接用来循环。

================================

ary = []

3.times{|i| ary << i}

p ary          #=>[0,1,2]

 

ary = []

2.upto(5){|i| ary << i}

p ary          #=>[2,3,4,5]

 

ary = []

5.downto(2){|i| ary << i}

p ary          #=>[5,4,3,2]

 

ary = []

10.step(20,3){|i| ary << i}

p ary           #=>[10,13,16,19]

10.step(2,-3){|i| ary << i}

p ary           #=>[10,7,4]

================================



{十一月 23, 2009}   ruby学习笔记(3)

1) sleep方法。 ruby中也有定时器,sleep相当于js中的setTimeout函数,不同的是sleep后的参数单位是秒,不是微秒。

2)ruby的函数中return是可以省略的,如果省略,方法中的最后一个语句的计算值会是返回值。

========================================

def area(x,y,z)

    xy = x * y

    yz = y * z

    zx = z * x

    (xy + yz +zx) * 2

end

p area(2,3,4)             #=>52

========================================

3) 判断对象的类型。 ruby有个和js中判断对象类型相近的方法,instance_of?。除了instance_of?之外,ruby的对象还有个很好用的方法,叫class,通过class方法可以直接得到对象的类型,需要注意的是.class返回的不是字符串,而是类。

========================================

str = “abc”

arr = [1,2,3]

p str.class   #=> String

p arr.class   #=> Array

p str.instance_of?(String)   #=> true

p arr.instance_of?(Array)    #=> true

p str.class == String     #=> true

========================================

和js一样,ruby中所有的类都继承自Object。但和js不一样的是,js的instanceof可以一直往上追踪,但ruby不行,ruby为往上追踪提供了另外一个方法is_a?。例如

=========================================

js:

var arr = [1,2,3];

alert(arr instanceof Array);                //true

alert(arr instanceof Object);              //true

ruby:

arr = [1,2,3]

p arr.instance_of?(Array)               #=> true

p arr.instance_of?(Object)              #=> false

p arr.is_a?(Object)                         #=> true

==========================================

4) ruby中的常量真是容易定义,用大写字母开头的就是常量了。常量在修改值的时候会报警告。

5)类名。和js不一样的是,js中是出于习惯,提倡类名首字母大写,并没有做硬性要求。ruby的类名却强制性要求首字母大写。原因是ruby要求类名必须为常量。

6)构造函数。ruby的构造函数并不是和类名同名的方法,而是统一使用initialize方法。一般语言都可以设定构造函数的访问性,设计模式中的单独模式就是通过构造函数的访问性做的文章。as3中强制构造函数为public,而ruby强制构造函数为private。

7) 实例化。 ruby的实例化一个类,不是通过new 类名()这种通用方式,而是通过类名.new()。奇怪的ruby语法@_@。

8) 属性的访问性。 和java一样,ruby并不支持直接访问类中的属性,如果要访问类中的属性,需要先通过attr_reader:属性名(只读),attr_writer:属性名(只写),attr_accessor:属性名(读写)来设定属性的访问权限。ruby中没有var关键字,不能通过函数产生变量的作用域。在js里,我们可以在类中定义一个私有变量,在所有的方法中调用。私有变量只要定义为和方法在同一级别,那么它就可以在各个方法中负责通信。ruby中不能使用这种方法,ruby在类里没办法定义变量,只能在方法中定义变量。方法和方法之间如果想通信只能通过@变量,也就是实例变量进行通信。@变量就像是js中的this.xxx变量一样,但js中的this.xxx只能是public的,可读可写,ruby通过attr_xxxx可以控制@变量的访问性。

9)方法的访问性。方法的访问性是通过public,private和protected进行限制的。和一般语言将访问性关键字放在方法前面不同的是,ruby的访问性是通过public :方法名1,方法名2。。。这样的方式进行声明的。属性的访问性可以放在前面,但方法的访问性要放在方法之后,如果放在方法前面会出现方法未定义的报错。除了初始化方法恒化private,其它方法缺省为public。

10)类方法(静态方法)。 ruby中定义类方法有三种方法。

=========================================

1)

class HelloWorld

   def HelloWorld.hello(name)

        print name,” said Hello.”

    end

end

HelloWorld.hello(“John”)

2)

class HelloWorld

..

end

class << HelloWorld

   def hello(name)

        print name,” said Hello.”

    end

end

HelloWorld.hello(“John”)

3)

class HelloWorld

   def self.hello(name)

        print name,” said Hello.”

    end

end

HelloWorld.hello(“John”)

=========================================

需要注意的是,类方法不能访问实例变量。

11)类变量(静态变量)。ruby中类变量是通过加@@标识的。

12)类常量。类中还可以定义常量,还是要求大写字母开头。类中不能定义和方法平缓的变量,但是可以定义和方法平级的常量,常量可以被所有方法调用。类常量的调用方法是类名::常量名。

13)继承。 ruby中的继承不是使用extend关键字,它更简洁,使用<就可以了。ruby也只支持单继承。

14) 类的示例。

========================================

class Dog
attr_accessor:name
def initialize(name = “wang cai”)
   @name = name
end
def call
   print “I’m a dog , my name is “, @name ,”\n”,Version,”\n”
end
def self.move(num=0)
   print “Dog had moved “,num,” bu\n”
   print Version,”\n”
end
Version = “1.0″
public :call
end

a = Dog.new
a.name = “huan huan”
a.call
Dog.move(5)

class BigDog < Dog
def call
   print “I’m a big dog , my name is “, @name,”\n”
end
end

b = BigDog.new(“abc”);
b.call
print Dog::Version

========================================

15)模块。模块是ruby特有的功能之一。模块和类很像,但和类最大的不同在于模块不能实例化,也不能继承。模块的作用有两个,一个是用于提供命名空间。第二提供Mix-in功能。Mix-in和继承很像,但它不是继承,在《javascript设计模式》一书里,将Min-in称为掺元继承,YUI提供的augment方法,思路就是Mix-in。模块是通过include关键字读入的,它和as中的with()方法有相似的地方,include了文件之后,前辍就可以不用写了。

16)模块的常量和类常用调用方法一样。模块名::常量名。模块的方法调用和类的方法调用不同,可以使用模块::方法名,也可以使用模块.方法名。

17)模块定义的方法默认是不对外部公开的,(模块内没有public private protect关键字),要将方法对模块外部公开,必须使用module_function。

===================================

module HelloModule

   Version = “1.0″

    def hello(name)

       print “Hello, “,name,”.\n”

     end

      module_function : hello

end

p HelloModule::Version          #=>”1.0″

HelloModule::hello(“Alice”)      #=> hello, Alice.

include HelloModule

p Version         #=>”1.0″

hello(“Alice”)    #=>Hello, Alice

===================================



{十一月 22, 2009}   ruby学习笔记(2)

1)ruby的语句可以换行。这一点和js不同,js中换行视作一行语句结束,相当于在句尾加了“;”号,如果一条语句换行写,会报错。ruby中语句可以换行,而且为了提高可读性,bury鼓励不使用“;”号,希望一行语句只写在一行里,可以的话,不要在同一行里写多条语句。

2)ruby中if,while等语句都不带{}号,相反,一些方法例如each则会带{},习惯了C系的语法,看着还真不习惯。总之因为不带{},所以在写if等语句时,一定要注意缩进,不然程序没法看了。

3)ruby中空格不能随便乱加,如果要加空格让程序好看一点,一定要注意讲求平衡。例如:

==============================

a+b

a + b 的效果相同

a +b 效果却等同于 a(+b),a()方法传入+b作为参数

==============================

4) to_i 方法。字符串转换成数字类型。相当于js中的parseInt()。

5) 布尔型转换。 在ruby中,布尔型也是为true和false,同其它语言一样,其它类型的值也能和布尔型进行隐式转换。但和大多数语言不同的是,在ruby中,false和nil以外所有的对象都为真,false和nil为假。包括0,在ruby中其实都是相当于真,这点和一般的语言不大一样。另外,ruby是个支持谓语的语言,鼓励返回布尔型数据的方法命名时加上“?”,这么做也是为了提高可读性。例如 isNumber? isGood?

6) 条件判断。 在ruby中,条件判断有一点很奇怪的是else if的写法,既不是“else if”也不是“elseif”,是“elsif”,汗,为啥把那个e给省掉了?看着多别扭啊。。。

============================

a = ARGV[0]
b = ARGV[1]
if a > b then
print “a > b”
elsif a == b then
print “a = b”
else
print “a < b"
end

============================

除了if,ruby中还提供了unless方法,语法和if一样,但和if正相反的是,unless中的条件不成立时,才会执行。

7) case语句。 ruby 中的case语句相当于其它语言中常用的switch,但ruby中的格式奇怪一点,功能也更强一点:

=============================

=begin

这是一般的用法

=end

tags = ["A","IMG","PRE"]

tags.each{ | tagname |

case tagname

when "P","A","I","B" then #bury这里可以写多个参数,用逗号隔开

print tagname,"has child.\n"

when "IMG","BR" then

print tagname,"has no child.\n"

else

print tagname,"cannot be used.\n"

end

}

=begin

when 里还可以放 String,Numberic之类的类型名,判断类型

=end

array = ["aa",1,nil]

item = array[0]

case item

when String

puts "item is a String."

when Numberic

puts "item is a Numeric."

else

puts "item is a something."

end

=begin

when 里还可以放正则表达式

=end

case line

when /^From:/i

print "找到寄件人了。\n"

when /^To:/i

print "找到收件人了。\n"

else

print "啥也没找到。"

end

=============================

需要注意的是,ruby中的when后面的条件不会自动转换类型,比如说1和"1"是不一样的。另外,很重要的一点是,when后面的语句不需要加break,这和C系的switch是不一样的。

8) ===。ruby中也有===号,但它和js中的===并不相同,ruby中的===左边可以是数字、字符串,也可以是正则,还可以是类型。

=============================

p (2 === 2) #=> true

p /zz/ === “zyzzy” #=> 2

p String === “xyzzy” #=>true

=============================



{十一月 20, 2009}   ruby学习笔记(1)

1) ruby的函数在调用的时候可以加括号,也可以不加括号。

函数定义的格式也比较奇怪:

==============================

def hello

print(“Hello World”)

end

hello()

==============================

2) ruby的输出方法有print,puts,p和pp。其中print是普通输出,它接受多个参数,在输出的时候会把所有参数拼起来然后输出;puts和print类似,不同的地方在于puts会在输出之后自动加上换行,如果传了多个参数,那个每个参数后都会自动加上换行;p和pp设计的目的都是为给程序员调试用的,它们输出的信息能包含更多信息,例如字符串在输出的时候会加上引号,pp和p不同的地方在于pp输出时会自动加入缩进和换行,让数据显示时的可读性更好。

3)单引号和双引号。和php一样,单引号中不能包含变量,双引号中可以包含变量。在ruby中,单引号中的\n这样表示换行之类的转义字符都会无效,直接输出出来。

4)注释。 ruby中的注释和c系语言不同,不是使用//和/**/,取而代之的是#和=begin,=end。

=============================

=begin

我是一个多行注释哦,

我换行了,

我又换行了

=end

# 我是一个单行注释

=============================

5) if判断。 也和C系不同,看起来更像是vb的语法。没有{}这样明显的分隔,如果不加上缩进的话,可读性该有多差啊@_@

=============================

if a >= 10 then

print(“big”)

else

print(“small”)

end

==============================

6) 循环。使用while:

==============================

i = 1

while i <= 10

print(i,"\n")

i = i + 1

end

==============================

使用times方法。当循环次数确定时,使用times方法会更简单:

==============================

100.times {|i|

print "hello ",i,"\n"

}

100.times do |i|

print "hello",i,"\n"

end

==============================

使用for。ruby的for有两种用法,一种是类似于C系的for(var i=0;i

==============================

sum = 0

for i in 2..5

sum += i

end

print sum

==============================

另一种类似于js的for(var p in Obj){}:

==============================

names = ["a","b","c"]

for name in names

print name,"\n"

end

==============================

和js的for (p in obj)不同的是,这里的p不是索引。例如上面代码的输出不是0,1,2,而是"a","b","c"。

如果换成是hash,又会怎么样呢?

==============================

names = {"a" => 1,”b” => 2,”c” => 3}

for name in names

print name,”\n”

end

==============================

输出是什么呢?a1,b2,c3,直接将键和值拼起来一块儿输出了。

ruby 的退出循环也比较奇怪。break和C系一样,C系的continue在ruby中叫next。注意,exit是退出整个程序,不是退出循环。

7) 迭代。 其实迭代也是我们熟悉的循环中的一种。和C第语言不同的是,对于复杂数据类型,比如数组,我们使用的不是for(var i=0,n=arr.leng;i

===============================

#数组

name = ["a","b","c"]

name.each{| n |

print n,"\n"

}

#hash

a = {"name" => “adang” , “sex” => “male”}

a.each{| key , value |

print key , ” : ” , value , “\n”

}

===============================

8) hash。 ruby也支持hash数据。和js不同的是,js的hash格式是{name1 : value1 , name2 : value2},而ruby的hash格式不是用:分隔,而是=>,这种使用习惯更像php。在调用hash数据时,js可以通过hash[name],或者hash.name的方式调用,而ruby只能通过hash[name]调用。

==============================

a = {“name” => “adang”,”sex” => “male”}

print a["name"]

==============================

9) 数组。 ruby的数组和js没太大区别,也可以通过 a = [] 来快速定义一个数组,有点奇怪的是ruby中数组长度不是通过arr.length来获得的,而是通过arr.size,这里size不是属性而是方法。

10) 正则。 和js一样,ruby的正则也可以通过/abc/的形式创建,但它的匹配方法和js不同,js中最常用的匹配方法是test,/abc/.test(str)是最常用的方式。在ruby中,匹配是通过 =~ 运算符来实现的,如果匹配成功,返回索引值,如果匹配失败,返回空值nil。nil应该相当于js中的null了:

==============================

p /Ruby/ =~ “Ruby” #=> 0

p /Ruby/ =~ “Diamond” #=> nil

==============================

11) ARGV数组。 这个数组是用来保存命令行对指令脚本传入的实参,类似于js中的augments数组。

12)读取文件。 读取文件的方式和php有点像,也是先打开文件,然后读取内容,最后关闭文件。

==============================

#整篇读取

filename = ARGV[0]

file = open(filename)

text = file.read

print text

file.close

#结合正则表达式,逐行读取 (我怎么看着这么像读取数据库中的数据的形式呢?)

pattern = Regexp.new(ARGV[0])

filename = ARGV[1]

file = open(filename)

while text = file.gets do

if pattern =~ text

print text

end

end

file.close

==============================

13) 将输出保存到文件中。 ruby比起js可以做更多的事了,比如说,读取或输出文本到文件,在ruby中将输出结果存在文件里非常简单,执行程序的时候,在指令的后面加上 “>文件名”,则输出就会被存在文件里。

==============================

> ruby test.rb > test.html

==============================

14) require。 像大多数语言一样(js除外),ruby支持require,需要被require的文件只需要被 require “fileName“就可以被包含进来了,值得注意的是,fileName可以省掉”.rb”后辍。

15) 全局变量和局部变量。 js的全局变量和局部变量是通过var关键字结合函数作用域实现的,在ruby中,是通过$符号来区别全局变量和局部变量的。比如说a.rb和b.rb同时都定义了$str和str两个变量,a.rb里require了b.rb文件,那么b.rb中的$str会影响到a.rb文件,因为他们是同一个变量,而b.rb中的str不会影响到a.rb中的str。

16)==,eql和equal。 在ruby中所有的对象都持有身份标识(ID),它是ruby原生支持的。这让我想起YUI了,YUI中也会自动对对象生成ID作为身份标识,不仅是DOM对象,也包括程序中的对象,这点和ruby异曲同工,只是ruby原生就支持,通过object_id可以获得。

==============================

ary1 = []

p ary1.object_id #=> 67653636

==============================

判断两个给定的对象是不是同一对象(ID相同),可以通过equal?方法来进行判断。

==============================

str1 = “foo”

str2 = str1

str3 = “f” + ”o“ + “o”

p str1.equal?(str2) #=> true

p str1.equal?(str3) #=> false

==============================

在这里有个概念需要清楚,在ruby中,一切数据都是对象,”foo”在这里是作为一个对象存在的,这点和as3一样,str2 = str1这一步的时候,其实不是复制了一份”foo”字符传给了str2,而是直接将str1的址传给了str2,此时str1和str2指向的是同一个内存地址,这么设计的目的当然是为了节约内存。equal?()比较的应该是内存地址是否一致,而不是“值”是否一致。在js中,传值还是传址,是根据数据类型决定的,赋值时无法指定,string,num等等基本类型是传值,array,hash等复杂类型是传址。php里传值还是传址是通过有无&符号决定的,有&传址,无&传值。ruby里只会传址,不会传值。但和as3一样,虽然是传址,但其实它不是普通的传址,而是传的一种“不变对象”,当“不变对象”的值被改动的时,其实并不是改变“不变对象”本身,而是新生成一个不变对象,而将旧的不变对象由垃圾回收机制自动回收。关于这一点,可以参考黑羽的《action script3殿堂之路》第21页“基元数据类型的深入讨论”。

前面说的是“址”的比较,对于“值”的比较,ruby提供了==和eql方法,==和eql之间的关系就相当于js中的==和===关系。

==============================

p 1.0 == 1 #=> true

p 1.0 eql?1 #=> false

==============================




about

打造高品质的前端代码

pages
categories
archive
et cetera