ror:Ruby on Rails
导言
承接前文!
本部分涉及的内容主要为Ruby基础,相对简单,所以只贴代码并加上了注释,不对代码进行详细解释。
前方高能,保护眼睛。
创建并切换分支
git checkout -b rails-favored-ruby
自定义辅助方法
辅助方法定义在app/helper目录下的文件中:
# app/helper/application_helper.rb
module ApplicationHelper
def full_title(page_title = '')
base_title = "Microblog"
if page_title.empty?
base_title
else
page_title + " | " + base_title
end
end
end
此时,可将标题代码改为:
# app/views/layouts/application.html.erb
... ...
<%= full_title(yield(:title)) %>
... ...
合并分支
git checkout master
git merge rails-flavored-ruby
git branch -d rails-flavored-ruby
git branch
字符串和方法
使用Rails控制台rails c
或者使用irb --simple-prompt
命令进行交互
注释
# single-line comment. # 单行注释
=begin
multiple-lines comments. # 多行注释
=end
双引号字符串
➜ microblog git:(rails-flavored-ruby) rails c
Running via Spring preloader in process 14069
Loading development environment (Rails 5.0.1)
2.3.3 :001 > "Hello, " + "Joshua" # 字符串连接
=> "Hello, Joshua"
2.3.3 :002 > name = "Joshua" # 字符串赋值
=> "Joshua"
2.3.3 :003 > "Hello, #{name}" # 字符串插值
=> "Hello, Joshua"
2.3.3 :004 > print "Joshua" # 打印字符串(不换行,返回nil)
Joshua => nil
2.3.3 :005 > puts "Joshua" # 打印字符串(换行,返回nil)
Joshua
=> nil
2.3.3 :006 > p "Joshua" # 打印字符串(带双引号、换行,返回原字符串)
"Joshua"
=> "Joshua"
2.3.3 :007 > (p "Joshua").length # 进行级联操作
"Joshua"
=> 6
2.3.3 :008 > (puts "Joshua").nil? # 返回nil
Joshua
=> true
单引号字符串
2.3.3 :001 > 'Joshua' # 字符串创建
=> "Joshua"
2.3.3 :002 > "Hello, " + 'Joshua' # 单引号字符串与双引号字符串类似
=> "Hello, Joshua"
2.3.3 :003 > name = 'Joshua' # 单引号字符串赋值
=> "Joshua"
2.3.3 :004 > '#{name}' # 不能进行插值
=> "\#{name}"
2.3.3 :005 > '\n' # 单引号字符串就是字面量,不进行转义
=> "\\n"
2.3.3 :006 > '\'' # 只有单引号需要转义
=> "'"
字符串基本用法见上述代码注释。
流程控制/方法定义
参考本人的这篇文章。
数组和值域
数组
2.3.3 :001 > a = [1,2,3,4,5] # 数组定义
=> [1, 2, 3, 4, 5]
2.3.3 :002 > a.first # 取第一个,相当于a[0]
=> 1
2.3.3 :003 > a.third # a[2]
=> 3
2.3.3 :004 > a.fifth # a[4]
=> 5
2.3.3 :005 > a.length # 数组长度
=> 5
2.3.3 :006 > a.empty? # 数组是否为空
=> false
2.3.3 :007 > a[1] # 数组取值
=> 2
2.3.3 :008 > a[-1] # 数组从后取值
=> 5
2.3.3 :009 > a.last # 最后一个值,相当于a[-1]
=> 5
2.3.3 :010 > a.include?(3) # 数组是否包含
=> true
2.3.3 :011 > a.shuffle # 数组置乱
=> [3, 4, 1, 2, 5]
2.3.3 :012 > a.sort # 数组排序
=> [1, 2, 3, 4, 5]
2.3.3 :013 > a.reverse # 数组逆序
=> [5, 4, 3, 2, 1]
2.3.3 :014 > a.shuffle # 置乱
=> [1, 2, 5, 4, 3]
2.3.3 :015 > a # 原数组不变
=> [1, 2, 3, 4, 5]
2.3.3 :016 > a.shuffle! # 带有!的表示破坏原数组
=> [1, 5, 3, 4, 2]
2.3.3 :017 > a # 原数组变了
=> [1, 5, 3, 4, 2]
2.3.3 :018 > a.push(8) # 插入值
=> [1, 5, 3, 4, 2, 8]
2.3.3 :019 > a << 9 # 插入值
=> [1, 5, 3, 4, 2, 8, 9]
2.3.3 :020 > a << "Hello" << "Joshua" # 连续插入(不同类型)
=> [1, 5, 3, 4, 2, 8, 9, "Hello", "Joshua"]
2.3.3 :021 > a.join # 合成一个数组
=> "1534289HelloJoshua"
2.3.3 :022 > a.join ',' # 使用,分隔合成数组
=> "1,5,3,4,2,8,9,Hello,Joshua"
2.3.3 :023 > a.join(',').split(',') # 使用split分割为数组
=> ["1", "5", "3", "4", "2", "8", "9", "Hello", "Joshua"]
数组基本用法见上述代码注释,比较简单不再赘述。
值域(Range)
2.3.3 :001 > 1..5 # 创建值域
=> 1..5
2.3.3 :002 > (1..5).to_a # 转变为数组
=> [1, 2, 3, 4, 5]
2.3.3 :003 > (1...5).to_a # ...表示忽略末尾
=> [1, 2, 3, 4]
2.3.3 :004 > a = %w[foo bar baz quux hello joshua] # 创建字符串数组
=> ["foo", "bar", "baz", "quux", "hello", "joshua"]
2.3.3 :005 > a[1..4] # 使用值域获取数组
=> ["bar", "baz", "quux", "hello"]
2.3.3 :006 > a[1...4] # 同样的道理
=> ["bar", "baz", "quux"]
2.3.3 :007 > a[2..-1] # 使用-1结尾表示到数组最后
=> ["baz", "quux", "hello", "joshua"]
2.3.3 :008 > a[2...-1]
=> ["baz", "quux", "hello"]
2.3.3 :009 > a[2...(a.length-1)] # 与-1相同
=> ["baz", "quux", "hello"]
2.3.3 :010 > ('a'..'f') # 使用字符创建值域
=> "a".."f"
2.3.3 :011 > ('a'..'f').to_a # 转变为数组
=> ["a", "b", "c", "d", "e", "f"]
练习
在逗号和空格处分拆字符串“A man, a plan, a canal, Panama”,把结果赋给变量 a
不指定连接符,把 a 连接起来,然后把结果赋值给变量 s 。
在空白处分拆 s ,然后再连接起来。使用以下代码中的方法确认得到的结果不是回文。使用downcase 方法,确认 s.downcase 是回文。
def palindrome_tester(s)
if s == s.reverse
puts "It's a palindrome!"
else
puts "It's not a palindrome."
end
end
代码如下:
a = "A man, a plan, a canal, Panama".split ', '
s = a.join
str = s.split.join
palindrome_tester str
palindrome_tester str.downcase
## 块
2.3.3 :001 > (1..3).each { |i| p i ** 2 } # 使用each方法,传递块(**表示幂)
1
4
9
=> 1..3
2.3.3 :002 > (1..3).each do |i| # 等价使用方式
2.3.3 :003 > p i ** 2
2.3.3 :004?> end
1
4
9
=> 1..3
常用的约定:
当块只有一行简单的代码时使用花括号形式
当块是一行很长的代码,或者有多行时使用 do..end 形式
2.3.3 :005 > 3.times { p "My name is Joshua" } # 循环多次
"My name is Joshua"
"My name is Joshua"
"My name is Joshua"
=> 3
2.3.3 :006 > (1..5).map { |i| i*2 } # map返回块中操作后的结果数组
=> [2, 4, 6, 8, 10]
2.3.3 :007 > %w[a b c].map { |c| c.upcase } # 同样
=> ["A", "B", "C"]
2.3.3 :008 > %w[a b c].map &:upcase # 可以简写为这样,不好理解
=> ["A", "B", "C"]
#### 练习
创建值域 0..16,把前 17 个元素的平方打印出来。
(0..16).each { |number| p number ** 2 }
定义一个名为 yeller 的方法,它的参数是一个由字符组成的数组,返回值是一个字符串,由数组中字符的大写形式组成。确认 yeller([’o’, ’l’, ’d’]) 的返回值是 OLD 。提示:要用到 map 、upcase 和 join 方法。
def yeller(arr)
arr.map(&:upcase).join
end
定义一个名为 random_subdomain 的方法,返回八个随机字母组成的字符串。
def random_subdomain
('a'..'z').to_a.shuffle[0..7].join
end
把下列代码中的问号换成正确的方法,结合 split 、 shuffle 和 join 方法,把指定字符串中的字符打乱。
def string_shuffle(s)
s.?('').?.?
end
string_shuffle("foobar")
"oobfra"
> 修改代码如下:
>
def string_shuffle(s)
s.split('').shuffle.join
end
## 哈希和符号
2.3.3 :001 > user = {} # 创建空的哈希表
=> {}
2.3.3 :002 > user["name"] = "Joshua" # 设置值
=> "Joshua"
2.3.3 :003 > user["name"] # 取值
=> "Joshua"
2.3.3 :004 > user["password"] # 获取空值
=> nil
2.3.3 :005 > user # 显示
=> {"name"=>"Joshua"}
2.3.3 :006 > user = { "name" => "Joshua", "email" => "[email protected]" } # 创建非空的哈希表
=> {"name"=>"Joshua", "email"=>"[email protected]"}
2.3.3 :007 > user = { :name => "Joshua", :email => "[email protected]" } # 使用符号创建非空哈希表
=> {:name=>"Joshua", :email=>"[email protected]"}
2.3.3 :008 > user = { name: "Joshua", email: "[email protected]" } # 符号创建简写方式
=> {:name=>"Joshua", :email=>"[email protected]"}
2.3.3 :009 > user[:name]
=> "Joshua"
2.3.3 :010 > user[:email] = { netease: "[email protected]", gmail: "[email protected]" } # 嵌套哈希表
=> {:netease=>"[email protected]", :gmail=>"[email protected]"}
2.3.3 :011 > user
=> {:name=>"Joshua", :email=>{:netease=>"[email protected]", :gmail=>"[email protected]"}}
2.3.3 :012 > user.each do |key, value| # each遍历
2.3.3 :013 > p "Key: #{key}, Value: #{value}"
2.3.3 :014?> end
"Key: name, Value: Joshua"
"Key: email, Value: {:netease=>"[email protected]", :gmail=>"[email protected]"}"
=> {:name=>"Joshua", :email=>{:netease=>"[email protected]", :gmail=>"[email protected]"}}
2.3.3 :015 > user.each do |key, value| # inspect显示字面量
2.3.3 :016 > p "Key: #{key.inspect}, Value: #{value.inspect}"
2.3.3 :017?> end
"Key: :name, Value: "Joshua""
"Key: :email, Value: {:netease=>"[email protected]", :gmail=>"[email protected]"}"
=> {:name=>"Joshua", :email=>{:netease=>"[email protected]", :gmail=>"[email protected]"}}
**同样,用法见注释**
#### 练习
定义一个哈希,把键设为 'one' 、 'two' 和 'three' ,对应的值分别是 'uno' 、 'dos' 和 'tres' 。迭代这个哈希,把各个键值对以 "'#key' in Spanish is '#value'" 的形式打印出来。
ott = { "one" => "uno", "two" => "dos", "three" => "tres" }
ott.each do |key, value|
p "'#{key}' in Spanish is '#{value}'"
end
创建三个哈希,分别命名为 person1 、 person2 和 person3 ,把名和姓赋值给 :first 和 :last 键。然后创建一个名为 params 的哈希,让 params[:father] 对应 person1 , params[:mother] 对应 person2 ,params[:child] 对应 person3 。验证一下 params[:father][:first] 的值是否正确。
person1 = { first: "father_first", last: "father_last" }
person2 = { first: "mather_first", last: "mather_last" }
person3 = { first: "child_first", last: "child_last" }
params = { father: person1, mather: person2, child: person3 }
params[:father][:first]
定义一个哈希,使用符号做键,分别表示名字、电子邮件地址和密码摘要,把键对应的值分别设为你的名字、电子邮件地址和一个由 16 个随机小写字母组成的字符串。
info = { name: "Joshua", email: "[email protected]", password: ('a'..'z').to_a.shuffle[0..15].join }
找一个在线 Ruby API,查阅哈希的 merge 方法。下述表达式的值是什么?
{ "a" => 100, "b" => 200 }.merge({ "b" => 300 })
表示合并哈希,若键值重复则覆盖。
## Ruby类
#### 构造方法
2.3.3 :001 > str = "Joshua" # 构造字符串
=> "Joshua"
2.3.3 :002 > str.class # 获取类型
=> String
2.3.3 :003 > String.new("Joshua") # 使用类名构造对象
=> "Joshua"
2.3.3 :004 > str.class.new("Aber") # 同理
=> "Aber"
2.3.3 :005 > Array.new([1,2,3]) # 构造数组
=> [1, 2, 3]
2.3.3 :006 > Hash.new # 构造Hash
=> {}
2.3.3 :007 > h = Hash.new("Joshua") # 修改默认返回为Joshua
=> {}
2.3.3 :008 > h[:joshua]
=> "Joshua"
2.3.3 :009 > (1..10).class # 获取Range类型
=> Range
2.3.3 :010 > r = Range.new(1, 10) # 构造Range
=> 1..10
2.3.3 :011 > r == (1..10) # 证明相等
=> true
#### 类的继承
2.3.3 :001 > str = "Joshua"
=> "Joshua"
2.3.3 :002 > str.class.superclass
=> Object
2.3.3 :003 > str.class.superclass.superclass
=> BasicObject
2.3.3 :004 > str.class.superclass.superclass.superclass
=> nil
2.3.3 :005 > Hash.superclass
=> Object
2.3.3 :006 > Array.superclass
=> Object
2.3.3 :007 > Range.superclass
=> Object
2.3.3 :008 > class Word < String # 继承String
2.3.3 :009?> def palindrome?
2.3.3 :010?> self == self.reverse # self表示对象本身
继承了reverse方法,可以简写为self == reverse
2.3.3 :011?> end
2.3.3 :012?> end
=> :palindrome?
2.3.3 :013 > w = Word.new("abcba")
=> "abcba"
2.3.3 :014 > w.palindrome? # 自定义方法
=> true
2.3.3 :015 > w.length # 拥有父类方法
=> 5
2.3.3 :016 > w.class.superclass # 查看父类
=> String
#### 修改内置类
2.3.3 :001 > class String # 修改内置String类,添加功能
2.3.3 :002?> def palindrome?
2.3.3 :003?> self == reverse
2.3.3 :004?> end
2.3.3 :005?> end
=> :palindrome?
2.3.3 :006 > "abcba".palindrome?
=> true
2.3.3 :007 > class String # 再次修改
2.3.3 :008?> def shuffle
2.3.3 :009?> self.split('').shuffle.join
2.3.3 :010?> end
2.3.3 :011?> end
=> :shuffle
2.3.3 :012 > "joshuaber".shuffle
=> "rbhjoeaus"
2.3.3 :013 > "joshuaber".palindrome? # 之前添加的方法仍然可用
=> false
2.3.3 :014 >
#### 自定义类
关于类的定义及存取器的定义,参考[这里](http://www.jianshu.com/p/437d5f947427)。啥也不说了,看代码吧:
```ruby
class User
attr_accessor :name, :email
def initialize(attributes = {})
@name = attributes[:name]
@email = attributes[:email]
end
def format_user
"#{@name} <#{@email}>"
end
end
user = User.new
p user
p user.name
user.name = "Joshua"
p user.name
user.email = "[email protected]"
p user.email
p user.format_user
juser = User.new(name: "Joshua", email: "[email protected]")
p juser.format_user
参考
《Rails Tutorial 4th》