在 Ruby 中,一切皆对象,包括字符串和 nil 都是。
字符串
"foo" + "bar" # 字符串拼接
=> "foobar"
first_name = "Michael" # 变量赋值
"#{first_name} Hartl" # 字符串插值 #{变量名}
=> "Michael Hartl"
# 关于单双引号
Ruby 不会对单引号字符串进行插值操作
"foobar".length # 获取字符串长度
=> 6
ruby中自带函数
# 是否为空 empty? 方法
# 注意,empty? 方法末尾有个问号,这是 Ruby 的约定,说明方法返回的是布尔值,即 true 或 false。
"foobar".empty?
=> false
"".empty?
=> true
# if else 用法
if s.nil?
"The variable is nil"
elsif s.empty?
"The string is empty"
elsif s.include?("foo")
"The string includes 'foo'" # 是否包含 'foo'
end
=> "The string includes 'foo'"
# &&(与)、||(或)和 !(非)运算符
x = "foo"
y = ""
puts "Both strings are empty" if x.empty? && y.empty?
=> nil
puts "One of the strings is empty" if x.empty? || y.empty?
=> "One of the strings is empty"
=> nil
puts "x is not empty" if !x.empty?
=> "x is not empty"
=> nil
# to_s 方法基本上可以把任何对象转换成字符串
nil.to_s
=> ""
nil.empty?
NoMethodError: undefined method `empty?` for nil:NilClass
nil.to_s.empty? # 消息串联
=> true
# 测试对象是否为空
"foo".nil?
=> false
"".nil?
=> false
nil.nil?
=> true
# if 关键词 用法 表达式为真值时才执行的语句
# 还有个对应的 unless 关键字也可以这么用
puts "x is not empty" if !x.empty?
string = "foobar"
puts "The string '#{string}' is nonempty." unless string.empty?
nil 对象的特殊性,除了 false 本身之外,所有 Ruby 对象中它是唯一一个布尔值为“假”的。
我们可以使用 !!(读作“bang bang”)对对象做两次取反操作,把对象转换成布尔值:
!!nil
=> false
除此之外,其他所有 Ruby 对象都是“真”值,数字 0 也是:
!!0
=> true
数组
# 字符串转为数组 split
"foo bar baz".split # 把字符串拆分成有三个元素的数组
=> ["foo", "bar", "baz"]
# 根据字符 转化
"fooxbarxbazx".split('x')
=> ["foo", "bar", "baz"]
a = [42, 8, 17]
a[0] # Ruby 使用方括号获取数组元素
=> 42
a[-1] # 索引还可以是负数
=> 17
a.first
=> 42
a.second
=> 8
a.last == a[-1] # 用 == 运算符对比 != | > | < | <= | >=
=> true
# 求数组长度
x = a.length # 和字符串一样,数组也可以响应 length 方法
=> 3
a.empty?
=> false
a.include?(42) # 是否存在42这个值
=> true
a.sort # sort 升序排序
=> [8, 17, 42]
a.reverse # 数组反转 | 字符串反转 也是这个
=> [17, 8, 42]
a.shuffle # shuffle 随机排序
=> [17, 42, 8]
# 修改数组中值的顺序[改变key值],加上 !
a.sort!
# 向数组中追加元素
a.push(6) # 把 6 加到数组末尾
=> [42, 8, 17, 6]
a << 7 # 把 7 加到数组末尾
=> [42, 8, 17, 6, 7]
a << "foo" << "bar" # 串联操作
=> [42, 8, 17, 6, 7, "foo", "bar"]
# join 数组转化为字符串 与 split 相反
a.join # 没有连接符
a.join(', ') # 连接符是一个逗号和空格
值域
# 值域(range)
0..9
# 转为数组 to_a
(0..9).to_a # 调用 to_a 时要用括号包住值域
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 值域也可以使用字符串定义
('a'..'e').to_a
=> ["a", "b", "c", "d", "e"]
# 值域经常用于获取数组的一组元素
a = %w[foo bar baz quux] # %w 创建一个元素为字符串的 数组
=> ["foo", "bar", "baz", "quux"]
a[0..2]
=> ["foo", "bar", "baz"]
# 获取2至数组最后一位的元素
a[2..(a.length-1)] # 显式使用数组的长度
=> [2, 3, 4, 5, 6, 7, 8, 9]
a[2..-1] # 小技巧,索引使用 -1
=> [2, 3, 4, 5, 6, 7, 8, 9]
块
# 遍历
(1..5).each { |i| puts 2 * i }
2
4
6
8
10
=> 1..5
# 说明 -------
在值域 (1..5) 上调用 each 方法,然后又把 { |i| puts 2 * i } 这个块传给 each 方法。
|i| 两边的竖线在 Ruby 中用来定义块变量。只有方法本身才知道如何处理后面跟着的块。
这里,值域的 each 方法会处理后面的块,块中有一个局部变量 i,each 会把值域中的各个值传进块中,
然后执行其中的代码。
花括号是表示块的一种方式,除此之外还有另一种方式:
# ------------
(1..5).each do |i|
puts 2 * i
end
# 结果和上面的一样
## 块中的内容可以多于一行,而且经常多于一行。
## 当块只有 一行简单的代码时 使用 花括号 形式;
## 当块是一行很长的代码,或者有多行时使用 do..end 形式:
(1..5).each do |number|
puts 2 * number
puts '-'
end
# 其他遍历
3.times { puts "Betelgeuse!" } # 3.times 后跟的块没有变量
"Betelgeuse!"
"Betelgeuse!"
"Betelgeuse!"
=> 3
(1..5).map { |i| i**2 } # ** 表示幂运算
=> [1, 4, 9, 16, 25]
%w[a b c] # 再说一下,%w 用于创建元素为字符串的数组
=> ["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"]
# 简写
%w[A B C].map(&:downcase)
=> ["a", "b", "c"]
散列[关联数组]和符号
user = {} # {} 是一个空散列
=> {}
user["first_name"] = "Michael" # 键为 "first_name",值为 "Michael"
=> "Michael"
user["last_name"] = "Hartl" # 键为 "last_name",值为 "Hartl"
=> "Hartl"
user["first_name"] # 获取元素的方式与数组类似
=> "Michael"
user # 散列的字面量形式
=> {"last_name"=>"Hartl", "first_name"=>"Michael"}
# => 创建散列
user = { "first_name" => "Michael", "last_name" => "Hartl" }
=> {"last_name"=>"Hartl", "first_name"=>"Michael"}
# 在 Rails 中用符号(Symbol)做键很常见。符号看起来有点儿像字符串,只不过没有包含在一对引号中,
# 而是在前面加一个冒号。例如,:name 就是一个符号。你可以把符号看成没有约束的字符串
# 符号是 Ruby 特有的数据类型.
user = { :name => "Michael Hartl", :email => "[email protected]" }
=> {:name=>"Michael Hartl", :email=>"[email protected]"}
user[:name] # 获取 :name 键对应的值
=> "Michael Hartl"
user[:password] # 获取未定义的键对应的值
=> nil
# 散列的第二种表示方式
{ name: "Michael Hartl", email: "[email protected]" }
# 在散列字面量中,:name => 和 name: 作用一样。
# 如果要表示符号,只能使用 :name(冒号在前面)。
# 嵌套散列
params = {} # 定义一个名为 params(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]"
# 散列响应遍历
flash = { success: "It worked!", danger: "It failed." }
flash.each do |key, value|
puts "Key #{key.inspect} has value #{value.inspect}"
end
# inspect 方法,它的作用是返回被调用对象的字符串 字面量 表示形式
类
# String
# 字面构造方法
s = "foobar" # 使用双引号字面构造方法
=> "foobar"
s.class # 响应class方法,返回所属的类
=> String
#具名构造方法
s = String.new("foobar") # 字符串的具名构造方法
=> "foobar"
s == "foobar"
=> true
# Array
# 数组的构造方法 Array.new 可接受一个可选的参数指明数组的初始值
a = Array.new([1, 3, 2])
=> [1, 3, 2]
# Hash[散列]
h = Hash.new
=> {}
h[:foo] # 试图获取不存在的键 :foo 对应的值
=> nil
h = Hash.new(0) # 让不存在的键返回 0 而不是 nil
=> {}
h[:foo]
=> 0
# 不继承其他类
class Word
def palindrome?(string)
string == string.reverse
end
end
# 调用
w = Word.new # 创建一个 Word 对象
w.palindrome?("foobar")
=> false
w.palindrome?("level")
=> true
########################
# 继承 String 类
class Word < String # Word 继承自 String
# 如果字符串和反转后相等就返回 true
def palindrome?
self == self.reverse # self 代表这个字符串本身
# 其实,在类中调用方法或访问属性时可以不用 self.(赋值例外),因此也可以写成
# self == reverse
end
end
# 调用
s = Word.new("level") # 创建一个 Word 实例,初始值为 "level"
s.palindrome? # Word 实例可以响应 palindrome? 方法
=> true
s.length # Word 实例还继承了String的所有方法
=> 5
# 查找 s 的父类
s.class.superclass
s.class.superclass.superclass # Ruby 1.9 使用 BasicObject 作为基类
# blank? 检查是否为空字符串
"".blank?
=> true
" ".empty?
=> false
" ".blank?
=> true
nil.blank?
=> true
# 一个包含空格的字符串不是空的(empty),却是空白的(blank)。
# 还要注意,nil 也是空白的。因为 nil 不是字符串
class User
# 创建属性访问器存取方法
# 定义读值方法(getter)和设值方法(setter),用于读取和设定 @name 和 @email 实例变量
attr_accessor :name, :email
def initialize(attributes = {})
@name = attributes[:name]
@email = attributes[:email]
end
def formatted_email
"#{@name} <#{@email}>"
end
end
需要注意的:
// 在 Ruby 中,括号是可以省略的
// 调用函数时可以省略括号
stylesheet_link_tag('application', media: 'all',
'data-turbolinks-track': 'reload')
stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track': 'reload'
// 调用函数时,如果散列是最后一个参数,可以省略花括号
stylesheet_link_tag 'application', { media: 'all',
'data-turbolinks-track': 'reload' }
stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track': 'reload'
参考:
https://railstutorial-china.org/book/chapter4.html
https://www.railstutorial.org/book/rails_flavored_ruby