Ruby for Rails 最佳实践Ⅷ

第八章 控制流技术

一、条件代码执行

1. if 关键字及相关构造

if condition

  # code here, executed if condition uates to true

end

也可以将整个 if 子句放在一行,为此需要在条件后面插入 then 关键字

if x > 10 then puts x end

也可以使用分号来替代换行

if x > 10; puts x; end

作为 Ruby 一个特殊规则,也可以使用冒号代替 then

if x > 10: puts x; end

 

2. else:可以在 if 语句中提供一个 else 分支

if condition

  # code executed if condition is true

else

  # code executed if condition is false

end

 

3. elsif:使得条件逻辑可以层叠,形成比 if 和 else 更多的层次

if condition1

  # code executed if condition1 is true

elsif condition2

  # code executed if condition1 is false

  # and condition2 is true

elsif condition3

  # code executed if neither condition1

  # nor condition2 is true, but condition3 is

end

 

4. unless:有时想使用否定 if 条件:如果某件事不是真的,那么执行给定的代码块

方法一:使用 not 关键字

if not (x == 1)

 

方法二:使用否定操作符!

if !(x == 1)

 

方法三:使用 unless

unless x == 1

 

5. 条件修饰语:可以把条件判断直接放在语句的后面作为修饰语

puts "Big number!" if x > 100

它和下面代码等价

if x > 100

  puts "Big number!"

end

也可以使用 unless 来实现

puts "Big number!" unless x <= 100

条件修饰语具有会话的风格。它们不需要使用 end。不能用它们来完成太多的工作(不能带 else 或者 elsif 分支),但是在需要一个简单的条件判断时,它们往往非常合适。

 

6. case 语句

print "Exit the program? (yes or no): "

answer = gets.chomp

         case answer

         when "yes"

           puts "Good-bye!"

           exit

         when "no"

           puts "OK, we'll continue"

         else

           puts "That's an unknown answer -- assuming you meant 'no'"

end

 

when 子句的匹配方法由 ===(三等号操作符)判断,即

if "yes" === answer

  puts "Good-bye!"

  exit

elsif "no" === answer

  puts "OK, we'll continue"

else

  puts "That's an unknown answer—assuming you meant 'no'"

end

因此 case/when 逻辑的本质是 object === other_object;而 object === other_object 的本质是 object ===(other_object)。

 

二、用循环重复动作

1. 用 loop 方法实现无条件循环,下面两段代码是等价的

loop { puts "Looping forever!" }

loop do puts "Looping forever!" end

 

对循环进行控制(break 停止循环)

n = 1

loop do

  n = n + 1

  break if n > 9

end

 

使用 next 在没有完成本次循环的情况下跳到下一次循环

n = 1

loop do

  n = n + 1

  next unless n == 10

  break

end

 

2. 用 while 和 until 关键字实现条件循环

(1)while:在给定条件为真时循环执行代码

n = 1

while n < 11

  puts n

  n = n + 1

end

puts "Done!"

 

也可以把 while 子句放在循环的结束处,这时需要 begin/end 标记循环的头尾

n = 1

begin

  puts n

  n = n + 1

end while n < 11

puts "Done!"

 

(2)until:具有和 while 相同的用法,但是逻辑相反

n = 1

until n > 10

  puts n

  n = n + 1

end

 

(3)while 和 until 作为修饰语

和 if unless 一样,while 和 until 可以在语句的末尾用作修饰语

n = 1

n = n + 1 until n == 10

puts "We've reached 10!"

 

3. for/in 循环:基于值列表的循环

celsius = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

for c in celsius

  puts c

end

 

三、代码块、迭代器和 yield 关键字

1. 代码块:由任意多行 Ruby 代码构成,可以用大括号封装

object.method_name {

         # code inside block

}

也可以用 do/end 来封装

object.method_name do

         # code inside block

end

 

2. yield 关键字:如果在调用方法时提供了代码块,那么在该方法执行过程中可以将控制转移到该代码块(暂停方法的执行),执行代码块中的代码,最后再返回该方法继续执行

def demo_of_yield

  puts "Executing the method body..."

  puts "About to yield control to the block..."

  yield

  puts "Back from the block—finished!"

end

demo_of_yield { puts "> Control has been passed to the block!" }

该代码的输出如下

Executing the method body...

About to yield control to the block...

> Control has been passed to the block!

Back from the block—finished!

 

3.给代码块传递参数

可以通过 yield 将参数发送到代码

yield(x,y,z)

代码块接受参数的方法,不使用圆括号,而使用一对管道符号(||)

some_method {|a,b,c|

         # code here

}

示例如下

def yield_an_arg

  puts "Yielding 10!"

  yield(10)

end

yield_an_arg {|x| puts "> Code block received this argument: #{x}" }

 

4. 从代码块返回值

def more_yielding

  puts "The code block shall multiply a number by 10."

  result = yield(3)

  puts "The result of this operation is #{result}."

end

more_yielding {|x| x * 10 }

 

5. 执行多个迭代

迭代:方法匿名调用代码块的过程

迭代器:任何匿名调用代码块的方法

使用代码块来执行温度转换方法

def temp_chart(temps)

  for temp in temps

    converted = yield(temp)

    puts "#{temp}\t#{converted}"

  end

end

celsiuses = [0,10,20,30,40,50,60,70,80,90,100]

temp_chart(celsiuses) {|cel| cel * 9 / 5 + 32 }

 

6. Ruby 的代码块机制意味着:可以使用代码块来补足方法中没有完全定义的行为

我们可以使用同样的方法通过另外的方式转换温度:

fahrens = [32,62,92,122,152,182,212]

temp_chart(fahrens) {|fahr| (fahr - 32) * 5 / 9 }

 

7. 关于 for 的更多内容

for 的本质就是迭代器:for 是调用一个特殊的迭代器 each 的一种可选方式

下面两段代码是等价的

for x in [1,2,3,4,5]

  puts x * 10

end

[1,2,3,4,5].each {|x| puts x * 10 }

 

四、错误处理和异常

1. 异常是特殊类型的对象,它是 Exception 类或它的后代类的一个实例,抛出一个异常意味着:停止程序的正常执行,处理碰到的问题或者退出程序

要看看实际中的异常可以试一试:

F:\ruby_project>ruby -e '1./0'

Ruby 抛出一个异常

-e:1:in `/': divided by 0 (ZeroDivisionError)

        from -e:1

 

2. 常见的异常

异常名

常见原因

怎样抛出

RuntimeError

这是 raise 方法抛出的默认异常

raise

NoMethodError

对象收到一个找不到对应方法的消息

a = Object.new

a.some_unknown_method_name

NameError

解释器碰到一个不能解析为变量或方法名的标识符

a = some_random_identifier

IOError

读关闭的流(stream),写只读的流,或类似的操作

STDIN.puts("Don't write to

STDIN!")

Errno::error

与文件 IO 相关的一族错误

File.open(-12)

TypeError

方法接收到它不能处理的参数

a = 3 + "can't add a string

to a number!"

ArgumentError

传递的参数的数目出错

def m(x); end; m(1,2,3,4,5)

 

3. 用 rescue 块来营救程序异常

print "Enter a number: "

n = gets.to_i

begin

  result = 100 / n

rescue

  puts "Your number didn't work. Was it zero???"

  exit

end

puts "100/#{n} is #{result}."

 

指定想要营救的异常:rescue ZeroDivisionError

 

4. 显示抛出异常

可以给 raise 提供第二个参数,作为抛出异常时的消息字符串

def fussy_method(x)

  raise ArgumentError, "I need a number under 10" unless x < 10

end

fussy_method(20)

也可以在此例中使用 rescue

begin

  fussy_method(20)

rescue ArgumentError

  puts "That was not an acceptable number!"

end

 

5. 重新抛出异常

def reraiser(filename)

  file_handle = File.new(filename)

rescue Errno::ENOENT => e

  puts "Something's wrong with your filename...."

  raise e

end

注意:只要 rescue 子句是方法定义体的最后部分,就不喜欢显示地使用 being/end 分隔符;

方法自己扮演了异常块的 end 角色。

此例涉及的主要新技术是那个奇特的 rescue 行。=>e 构造将异常对象放入变量 e 中。

下面对该方法进行调用

reraiser("some_non_existent_filename")
输出以下内容

Something's wrong with your filename....

reraiser.rb:2:in `initialize': No such file

   or directory - some_non_existent_filename

   (Errno::ENOENT)

 

6. 创建异常类:通过从 Exception 或它的后代继承

class MyNewException < Exception

end

raise MyNewException, "some new kind of error has occurred!"

 

7. 异常及它们在 Rails 框架中的名字

ActiveController 库定义了 UnknownAction,  UnknownController, MissingTemplate 等异常,所有这些异常类都继承自中间级别的异常类 ActionControllerError,该类是 Ruby 内建的 StandardError类的子类。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值