请举例说明使用block
的方式,地点和原因。
# Block Method
def say_hello(&block)
puts "hello!"
block.call
end
say_hello { puts "hello again!" }
#=> hello!, hello again!
# Standard Method
def say_hello(block)
puts "hello!"
puts block
end
say_hello("hello again!")
#=> hello!, hello again!
显然,这个例子没有block
任何正义。谢谢您的帮助!
答案 0 :(得分:3)
people = ['bob', 'joe', 'ralph']
people.each { |person| puts "Hi, #{person}!" }
答案 1 :(得分:2)
在各种情况下,街区都是好的候选人。
在某些情况下,块不是您所见过的唯一解决方案,您可能已经能够在没有块的情况下执行类似的执行。例如,以下ActiveRecord模型语句
就是这种情况User.create! do |u|
u.email = "example@example.com"
u.password = "password"
end
没有块
u = User.new
u.email = "example@example.com"
u.password = "password"
u.save!
或
u = User.create!(email: "example@example.com", password: "password")
一般来说,你可以说块使代码更简洁和可读
File.open("file.txt") { |f| f.write("text") }
乍一看可以改写为
f = File.open("file.txt")
f.write("text")
f.close
这确实更加冗长。但还有更多。实际上,在块示例中,变量f
是局部块变量,并且在范围外不可见。这是块的第一个有趣的方面之一:范围。
但还有更多。我最喜欢使用的块之一是包装器。假设您要执行可能失败的代码块。当代码失败时,您希望在引发错误之前释放资源。你可以使用一个块
def safe
yield
ensure
# clean the house
end
实际上,这正是File.open
传递块时的作用。如果执行包装在一个块中,如果失败,该方法可确保文件处理程序关闭,这样就不会留下打开的文件连接。
另一个很好的例子是Timeout
库。
require 'timeout'
status = Timeout::timeout(5) {
# Something that should be interrupted if it takes more than 5 seconds...
}
如果要在执行时没有在合理的时间内终止时引发错误,可以将代码包装在一个块中。该块启动一个并行线程,该线程计算执行时间,如果块内的 块没有在线程结束之前结束,则会启动。
我挑战你实现没有块的相同代码。这肯定会很难。
一般来说,该块允许您为方法构建一个通用骨架,可以通过传递块在运行时进一步自定义。这些示例(Enumerable
方法,例如each
,Timeout
,Benchmark.ms
等等,可能是理解块功能的最佳示例。
答案 2 :(得分:0)
如何:
def say_hello(&block)
name = current_user.name
res = block.call(name)
res =+ ". and buy a car"
raw res
end
say_hello do |name|
"<div class='x1' > #{ name } </div>"
end
say_hello do |name|
"Hi #{name}"
end
say_hello do |name|
if name == 'Jack'
'U are so ugly'
else
name
end
end
其中:
say_hello
中定义的Rails helper
方法
用于Rails views
为什么: 灵活性,你没有创建新的方法只改变格式和创建大量的蹩脚方法(say_hello,say_hello_for_jack,say_hello_with_html ...)