什么是有用的块?

时间:2013-12-16 22:03:46

标签: ruby-on-rails ruby

请举例说明使用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任何正义。谢谢您的帮助!

3 个答案:

答案 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方法,例如eachTimeoutBenchmark.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 ...)