1. + 连接两个字符串
>> "foo" + "bar" # String concatenation
=> "foobar"
2.内嵌表达式
>> first_name = "Michael" # Variable assignment
=> "Michael"
>> "#{first_name} Hartl" # String interpolation
=> "Michael Hartl"
3.puts方法(put string)
>> puts "foo" # put string foo => nil
可以看到,puts方法打印出字符串的字面量之后,返回了一个nil方法(这是一个很特别的东西,后面分析)
4.puts方法会自动在行末增加一个换行符号\n,与之对应的是print方法
>> print "foo" # print string (same as puts, but without the newline) foo=> nil >> print "foo\n" # Same as puts "foo" foo => nil
5.单引号与双引号
>> 'foo' # A single-quoted string => "foo" >> 'foo' + 'bar' => "foobar"
>> '#{foo} bar' # Single-quoted strings don't allow interpolation => "\#{foo} bar"
单引号打印出所引的内容,而不会去执行引号内的内容。在¥,#这类特殊符号前会加\。
6.Ruby中任何东西都是对象,包括字符串和nil。
7.length方法
>> "foobar".length # Passing the "length" message to a string => 6
8.empty?方法
>> "foobar".empty? => false >> "".empty? => true
9.因为nil也是对象,所以nil也有方法。to_s可以将其变为字符串
>> nil.to_s
=> ""
10.nil本身不会对empty方法响应,而是nil.to_s
>> nil.empty? NoMethodError: You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.empty? >> nil.to_s.empty? # Message chaining => true
11.检验nil的方法nil?
>> "foo".nil?
=> false
>> "".nil?
=> false
>> nil.nil?
=> true
12.nil方法之前说过,很特说,那么它特殊在哪里。可以这样说,Ruby中,除了false这个布尔值是false,只有nil是false,可以通过以下验证
>> if nil
>> true
>> else
>> false # nil is false
>> end
=> false
>> if 0
>> true # 0 (and everything other than nil and false itself) is true
>> else
>> false
>> end
=> true
13.就像12所说的,Ruby中除了false和nil是false的,其他都是true,包括0。如上代码所示。
14.Ruby中方法的返回,默认返回最后一个语句,当然用return显式返回当然也没问题。
15.将字符串切割成数组.spilt方法:
默认使用
>> "foo bar baz".split # Split a string into a three-element array => ["foo", "bar", "baz"]
当然,spilt可以传参使用:
>> "fooxbarxbazx".split('x') => ["foo", "bar", "baz"]
>> "fooxxarxbazx".split('x') => ["foo", "","ar", "baz"]
16.像其他语言一样,Ruby数组的开始索引由0开始,负数表示倒数索引,-1表示最后一个
>> a = [42, 8, 17] => [42, 8, 17] >> a[0] # Ruby uses square brackets for array access. => 42 >> a[1] => 8 >> a[2] => 17 >> a[-1] # Indices can even be negative! => 17
17.数组特殊访问方法,first, second,last
>> a # Just a reminder of what 'a' is => [42, 8, 17] >> a.first => 42 >> a.second => 8 >> a.last => 17 >> a.last == a[-1] # Comparison using == => true
18.除了length方法,数组还有很多方法:
>> a => [42, 8, 17] >> a.sort => [8, 17, 42] >> a.reverse => [17, 8, 42] >> a.shuffle => [17, 42, 8] >> a => [42, 8, 17]
19.从上面最后行可以看出,虽然调用了很多方法,但是a的值是没有改变的,如何改变呢:
>> a => [42, 8, 17] >> a.sort! => [8, 17, 42] >> a => [8, 17, 42]
!方法(bang)就可以改变数组的值。
20.数组中插入元素
>> a.push(6) # Pushing 6 onto an array => [42, 8, 17, 6] >> a << 7 # Pushing 7 onto an array => [42, 8, 17, 6, 7] >> a << "foo" << "bar" # Chaining array pushes => [42, 8, 17, 6, 7, "foo", "bar"]
可以看出,除了push以外还可以<<用来插入元素
21.前面说了split方法,可以将字符串分割成数组,那么如何让数组元素组合起来呢?
>> a => [42, 8, 17, 7, "foo", "bar"] >> a.join # Join on nothing => "428177foobar" >> a.join(', ') # Join on comma-space => "42, 8, 17, 7, foo, bar"
可以看出,join方法,能够将数组元素组合起来,不管数组元素是什么类型,join之后,都是字符串类型。当然join也可以传参,如上所示。
22.range以及to_a方法
>> 0..9
=> 0..9
>> 0..9.to_a # Oops, call to_a on 9
NoMethodError: undefined method `to_a' for 9:Fixnum
>> (0..9).to_a # Use parentheses to call to_a on the range
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
可以看到..方法很是方便,当然如上所示,9没有to_a方法的,to_a是针对range的。
23.range可以很方便地取数组元素
>> a = %w[foo bar baz quux] # Use %w to make a string array.
=> ["foo", "bar", "baz", "quux"]
>> a[0..2]
=> ["foo", "bar", "baz"]
其中%w{String} 用于将一个字符串以空白字符切分成一个字符串数组,进行较少替换
range还有一种,除了两个点,还有三个点...,比如0...1,表示只取0,不能取到1。
24.range还有一种很性感的用法:
>> ('a'..'e').to_a => ["a", "b", "c", "d", "e"]
25.Ruby中的数组和range都有一个接受block的方法,这也是ruby的强大之处,往往令初学者迷惑:
>> (1..5).each { |i| puts 2 * i }
2
4
6
8
10
=> 1..5
上面这段代码,对range(1..5)调用了each方法,并且传递了一段block给each方法,|i|表示变量i,这段block将以i为变量,执行。
上面的这段代码也可以这样写:
>> (1..5).each do |i| ?> puts 2 * i >> end 2 4 6 8 10 => 1..5
后者比较常用在rails中。
26.其他一些常用的方法,这里,%w较为迷惑。上面已经解释过了。再次强调%w{String} 用于将一个字符串以空白字符切分成一个字符串数组,进行较少替换
>> 3.times { puts "Betelgeuse!" } # 3.times takes a block with no variables.
"Betelgeuse!"
"Betelgeuse!"
"Betelgeuse!"
=> 3
>> (1..5).map { |i| i**2 } # The ** notation is for 'power'.
=> [1, 4, 9, 16, 25]
>> %w[a b c] # Recall that %w makes string arrays.
=> ["a", "b", "c"]
>> %w[a b c].map { |char| char.upcase }
=> ["A", "B", "C"]
>> %w[A B C].map { |char| char.downcase }
=> ["a", "b", "c"]
map方法返回数组或者range应用了block之后的结果。
27.如果上面这些理解的差不多了,可以看看这句
('a'..'z').to_a.shuffle[0..7].join
全部字母组成的数组,大小为26,打乱顺序,然后取前8个,然后连接成字符串。
,可以运行每一步,来分析
>> ('a'..'z').to_a # An alphabet array => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] >> ('a'..'z').to_a.shuffle # Shuffle it. => ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q", "b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"] >> ('a'..'z').to_a.shuffle[0..7] # Pull out the first eight elements. => ["f", "w", "i", "a", "h", "p", "c", "x"] >> ('a'..'z').to_a.shuffle[0..7].join # Join them together to make one string. => "mznpybuj"
接下来是Hash和symbol
28.hash本质上是数组:当你把key当成整数来对待的时候。当然,hash与数组的不同也就在于,hash的key可以是任何东西,甚至对象。
>> user = {} # {} is an empty hash. => {} >> user["first_name"] = "Michael" # Key "first_name", value "Michael" => "Michael" >> user["last_name"] = "Hartl" # Key "last_name", value "Hartl" => "Hartl" >> user["first_name"] # Element access is like arrays. => "Michael" >> user # A literal representation of the hash => {"last_name"=>"Hartl", "first_name"=>"Michael"}
可以看到,hash的索引,跟数组是很像的。
29.hash用一对打括号,里面包含键值来生名,当然,没有包含键值的成为空hash,如上。这里要明确的是,hash的大括号跟block的大括号没有任何关联。
>> user = { "first_name" => "Michael", "last_name" => "Hartl" } => {"last_name"=>"Hartl", "first_name"=>"Michael"}
这里,遵循ruby的约定,括号两端加空格。约定,约定而已。
30,在Ruby中,我们大多使用的是string当作key,但是在rails中,我们更多用symbol来作为键,像这样:name.
>> "name".split('')
=> ["n", "a", "m", "e"]
>> :name.split('')
NoMethodError: undefined method `split' for :name:Symbol
>> "foobar".reverse
=> "raboof"
>> :foobar.reverse
NoMethodError: undefined method `reverse' for :foobar:Symbol
symbol代表着在编译期间不会变化的量。我们可以这样来定义,很rails,不是吗?
>> user = { :name => "Michael Hartl", :email => "[email protected]" } => {:name=>"Michael Hartl", :email=>"[email protected]"} >> user[:name] # Access the value corresponding to :name. => "Michael Hartl" >> user[:password] # Access the value of an undefined key. => nil
对于一个不存在的键,返回的是nil。ruby1.9之后也引入了这种表示方法。
当然,还有另外一种表示:
{ name: "Michael Hartl", email: "[email protected]" }
Ruby1.8.7以及之前的版本可以不太支持。
31.hash的值可以为任何东西
>> params = {} # Define a hash called 'params' (short for 'parameters'). => {} >> params[:user] = { name: "Michael Hartl", email: "[email protected]" } => {:name=>"Michael Hartl", :email=>"[email protected]"} >> params => {:user=>{:name=>"Michael Hartl", :email=>"[email protected]"}} >> params[:user][:email] => "[email protected]"
像上面这种嵌套的hash在rails中比较常见。
32.跟array和range一样,hash也有对应的each方法
>> flash = { success: "It worked!", error: "It failed." } => {:success=>"It worked!", :error=>"It failed."} >> flash.each do |key, value| ?> puts "Key #{key.inspect} has value #{value.inspect}" >> end Key :success has value "It worked!" Key :error has value "It failed."
注意到,数组的each方法的block接受一个变量,而hash的block需要两个参数(键值对)
33.接下来,我们有一个比较有用的方法inspect,它返回调用对象的一个字符串直面值,抽象啊- -|||
>> puts (1..5).to_a # Put an array as a string.
1
2
3
4
5
>> puts (1..5).to_a.inspect # Put a literal array.
[1, 2, 3, 4, 5]
>> puts :name, :name.inspect
name
:name
>> puts "It worked!", "It worked!".inspect
It worked!
"It worked!"
inspect跟p的意思差不多,其实,p方法就是inspect的简写:
>> p :name # Same as 'puts :name.inspect'
:name
34.约定!!约定!!
Ruby中方法参数的括号,可以省略;
# Parentheses on function calls are optional. stylesheet_link_tag("application", :media => "all") stylesheet_link_tag "application", :media => "all"
rails中,如果hash是最后一个参数,那么大括号也是可以省略的,
# Curly braces on final hash arguments are optional. stylesheet_link_tag "application", { :media => "all" } stylesheet_link_tag "application", :media => "all"
接下来,是对ruby中的类的总结
35.我们已经看到很多用class实例化的对象,也显式地这样做。比如,我们实例化一个string,用双引号,这是string的字面量构造
>> s = "foobar" # A literal constructor for strings using double quotes
=> "foobar"
>> s.class
=> String
除此之外,我们可以通过new显式地构造
>> s = String.new("foobar") # A named constructor for a string => "foobar" >> s.class => String >> s == "foobar" => true
数组跟字符串类似
>> a = Array.new([1, 3, 2]) => [1, 3, 2]
hash略微有所不同,数组构造的时候需要给定一个初始值,然后,hash有一个默认的初始值。
>> h = Hash.new
=> {}
>> h[:foo] # Try to access the value for the nonexistent key :foo.
=> nil
>> h = Hash.new(0) # Arrange for nonexistent keys to return 0 instead of nil.
=> {}
>> h[:foo]
=> 0
36.类的继承,用class方法可以得到当前实例的类,用superclass可以得到其父类。。。
>> s = String.new("foobar") => "foobar" >> s.class # Find the class of s. => String >> s.class.superclass # Find the superclass of String. => Object >> s.class.superclass.superclass # Ruby 1.9 uses a new BasicObject base class => BasicObject >> s.class.superclass.superclass.superclass => nil
37.为了说明继承问题,我们来看这样一个例子,判断是否为回文。
>> class Word
>> def palindrome?(string)
>> string == string.reverse
>> end
>> end
=> nil
>> w = Word.new # Make a new Word object.
=> #<Word:0x22d0b20>
>> w.palindrome?("foobar")
=> false
>> w.palindrome?("level")
=> true
再看下面的方法
>> class Word < String # Word inherits from String. >> # Returns true if the string is its own reverse. >> def palindrome? >> self == self.reverse # self is the string itself. >> end >> end => nil
>> s.class => Word >> s.class.superclass => String >> s.class.superclass.superclass => Object
可以明显看到继承的过程
38.修改内置类的方法
>> "level".palindrome?
NoMethodError: undefined method `palindrome?' for "level":String
>> class String
>> # Returns true if the string is its own reverse.
>> def palindrome?
>> self == self.reverse
>> end
>> end
=> nil
>> "deified".palindrome?
=> true
39.上面这种方法有好有坏,但在rails中,比较实用。
因为在web开发中,我们经常要阻止变量为空,比如,user name必须为除了空白符之外的字符,因此我们实现了blank?方法
>> "".blank?
=> true
>> " ".empty?
=> false
>> " ".blank?
=> true
>> nil.blank?
=> true
40分析一段rails中的user类
class User attr_accessor :name, :email def initialize(attributes = {}) @name = attributes[:name] @email = attributes[:email] end def formatted_email "#{@name} <#{@email}>" end end
首先,第一行
attr_accessor :name, :email
新建一个属性的accessor对应一个name和email,这样就新建了一个getter和setter方法,允许我们获取实例变量@name,@emal和赋值。Rails中实例变量的重要性在于,他们在views中是自动可见的。
然后再来看
def initialize(attributes = {})
@name = attributes[:name]
@email = attributes[:email]
end
initialize方法在Ruby中是很特别的:当我们执行User.new的时候,它被调用。它有一个参数。这里,attrbutes变量默认值为空的hash,因此当我们没有name或者email的时候,hash返回的是nil。因此当没有:name这个键的时候attributes[:name]为nil。
最后,这个类定义了一个叫做formmated_email的方法,使用内嵌表达式来建立一个email地址。
def formatted_email
"#{@name} <#{@email}>"
end
因为@name和@email都是实例变量,他们将在formatted_email方法中可见。