Rails中用到的Ruby知识小结

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方法中可见。

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Ruby)