Ruby on Rails 教程 (03)

Rails背后的Ruby

  • 字符串和方法
  • 常用数据类型(数组,值域,块,哈希,符号)
  • Ruby类

字符串和方法


# 注释
'foo'                  # 单引号字符串
"bar"                  # 双引号字符串
"foo" + "bar"          # 字符串连接
first_name = "Michael" # 变量赋值
"#{first_name} Hartl"  # 字符串插值
puts first_name        # 打印字符串
p first_name           # 打印字符串
print first_name       # 打印字符串

单引号和双引号字符串的区别:插值和转义

对象和消息传送

在 Ruby 中,一切皆对象,包括字符串和 nil 都是,对象的作用:响应消息


"foobar".length
"foobar".empty?
"".empty?
nil.empty?
nil.to_s.empty?
x = "foo"
puts "x is not empty" if !x.empty?
string = "foobar"
puts "The string '#{string}' is nonempty." unless string.empty?

定义方法


def string_message(str = '')
  if str.empty?
    "It's an empty string!"
  else
    "The string is nonempty."
  end
end

参数可选和默认值,不用显式返回,方法调用括号可选

标题的辅助方法


module ApplicationHelper
  def full_title(page_title = '')
    base_title = "Ruby on Rails Tutorial Sample App"
    if page_title.empty?
      base_title
    else
      page_title + " | " + base_title
    end
  end
end
          

数组(Array)


"foo bar baz".split
"fooxbarxbazx".split('x')
a = [42, 8, 17]
a[0]
a[-1]
a.first
a.last
a.length
a.empty?
a.include?(42)
a.sort
a.reverse
a.shuffle

数组(Array)


a.push 6
a.shift
a.pop
a << 7
a << "foo" << "bar"
a.join
a.join ","

值域(Range)


r = 0..9
r.to_a
a = %w[foo bar baz quux]
a[0..2]
a = (0..9).to_a
a[2..(a.length-1)]
a[2..-1]
('a'..'e').to_a

块(Block)

块就是闭包(closure),是一种匿名函数,其中附带了一些数据。


(1..5).each { |i| puts 2 * i }
(1..5).each do |i|
  puts 2 * i
end
3.times { puts "Betelgeuse!" }
(1..5).map { |i| i**2 }
%w[a b c].map { |char| char.upcase }
%w[A B C].map(&:downcase)
          

哈希(Hash)


user = {}
user["first_name"] = "Michael"
user["last_name"] = "Hartl"
user["first_name"]
user

user = { "first_name" => "Michael", "last_name" => "Hartl" }

符号(Symbol)


user = { :name => "Michael Hartl", :email => "michael@example.com" }
user[:name]
h2 = { name: "Michael Hartl", email: "michael@example.com" }

嵌套哈希


params = {}
params[:user] = { name: "Michael Hartl", email: "mhartl@example.com" }
params
params[:user][:email]
          

迭代器的Each方法


flash = { success: "It worked!", danger: "It failed." }
flash.each do |key, value|
  puts "Key #{key.inspect} has value #{value.inspect}"
end

重温引入 CSS 的代码


<%= stylesheet_link_tag 'application', media: 'all',
  'data-turbolinks-track' => true %>

# 调用函数时可以省略括号
stylesheet_link_tag('application', media: 'all',
  'data-turbolinks-track' => true)

# 如果最后一个参数是哈希,可以省略花括号
stylesheet_link_tag 'application', { media: 'all',
  'data-turbolinks-track' => true }

# 换行 v.s 不换行
stylesheet_link_tag 'application', { media: 'all', 'data-turbolinks-track' => true }
          

字面构造方法(Literal Constructor)


s = "foobar"
s.class

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

h = {foo: 'bar'}
h.class

具名构造方法(Named constructor)


s = String.new("foobar")

a = Array.new([1,3,2])

h = Hash.new(0)

类的继承


s = String.new("foobar")
s.class
s.class.superclass
s.class.superclass.superclass

自定义类


class Word
  def palindrome?(string)
    string == string.reverse
  end
end

w = Word.new
w.palindrome?("foobar")
w.palindrome?("level")

继承String


class Word < String
  def palindrome?
    self = self.reverse
  end
end

s = Word.new("level")
s.palindrome?
s.length

Ruby和其他语言相比,最强大的特性之一

修改内置的类(Open Class)


class String
  def palindrome?
    self == self.reverse
  end
end

"deified".palindrome?

用户类


# example_user.rb
class User
  attr_accessor :name, :email
  def initialize(attributes = {})
    @name = attributes[:name]
    @email = attributes[:email]
  end

  def formatted_email
    "#{@name} <#{@email}>"
  end
end

课后练习

  • 实现一个方法,随机打乱字符串输出 string_shuffle("foobar") => "oobfra"
  • 修改内置类String,实现shuffle方法
  • 创建三个哈希,分别命名为 person1 、 person2 和 person3 ,把名和姓赋值给 :first 和 :last 键。然后 创建一个名为 params 的哈希,让 params[:father] 对应 person1 , params[:mother] 对应 person2 , params[:child] 对应 person3 。验证一下 params[:father][:first] 的值是否正确。
  • 找一个在线版 Ruby API 文档,了解哈希的 merge 方法的用法。下面这个表达式的计算结果是什么? { "a" => 100, "b" => 200 }.merge({ "b" => 300 })

Q & A

下一课