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 => "michael@example.com" } => {:name=>"Michael Hartl", :email=>"michael@example.com"} >> 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: "michael@example.com" }
Ruby1.8.7以及之前的版本可以不太支持。
?
31.hash的值可以为任何东西
?
>> params = {} # Define a hash called 'params' (short for 'parameters'). => {} >> params[:user] = { name: "Michael Hartl", email: "mhartl@example.com" } => {:name=>"Michael Hartl", :email=>"mhartl@example.com"} >> params => {:user=>{:name=>"Michael Hartl", :email=>"mhartl@example.com"}} >> params[:user][:email] => "mhartl@example.com"
像上面这种嵌套的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方法中可见。
?
?
?
?
?
?
?
?
?
?
?
?