Ruby 中 block 是非常重要的,也是非常特别的一部分内容。 很多代码的重构都可以通过 code block 得以一种优雅的方式实现。 根据《Ruby 最佳实践》中的内容,我简单做一些小结。
(1..5).to_a.map { |i| i * 2 }
class SortedList
def initialize
@data = []
end
def <<(element)
(@data << element).sort!
end
def each
@data.each { |e| yield(e) }
end
end
File.open("some.txt") { |f| f << "some words" }
"This is a string".instance_eval do
"O hai, can has reverse? #{ revers }. kthxbye"
end
#=> "O hai, can has reverse? gnirts a si sihT. kthsbye"
>> foo = Hash.new { |h, k| h[k] = [] }
=> {}
>> foo[:bar]
=> []
>> foo[:bar] << 1 << 2 << 3
=> [1, 2, 3]
require "socket"
class Client
def initialize(ip = "127.0.0.1", port = 3333)
@ip, @port = ip, port
end
def send_message(msg)
socket = TCPSocket.new(@ip, @port)
socket.puts(msg)
response = socket.gets
ensure
socket.close if socket
end
def receive_message
socket = TCPSocket.new(@ip, @port)
response = socket.gets
ensure
socket.close if socket
end
end
这个代码明显不符合 DRY 的风格,所以利用 block 来重构一下:
require "socket"
class Client
def initialize(ip = "127.0.0.1", port = 3333)
@ip, @port = ip, port
end
def send_message(msg)
connection do |socket|
socket.puts(msg)
socket.gets
end
end
def receive_message
connection { |socket| socket.gets }
end
private
def connetcion
socket = TCPSocket.new(@ip, @port)
yield(socket)
ensure
socket.close if socket
end
end
if __FILE__ == $0
client = Client.new
["Hello", "My name is Greg", "Goodbye"].each do |msg|
response = client.send_message(msg)
puts response
end
end
#输出以下内容
#Hello from server at Wed Jul 23 16:15:37 ...
#Nice to meet you Greg!
#Goodbye from server at Wed Jul 32 ...
以上代码明显简洁了很多
require 'socket'
class Server
def initialize(port = 3333)
@server = TCPServer.new("127.0.0.1", port)
@handlers = {}
end
def handle(pattern, &block)
@handlers[pattern] = block
end
def run
while session = @server.accept
msg = session.gets
match = nil
@handlers.each do |pattern, block|
if match = msg.match(pattern)
break session.puts(block.call(match))
end
unless match
session.puts "Server received unknown message: #{msg}"
end
end
end
end
end
if __FILE__ == $0
server = Server.new
server.handle(/hello/i){ "Helllo from server at #{Time.now}" }
server.handle(/goodbye/i){ "Goodbye from server at #{Time.now}" }
server.handle(/name is (\w+)/){ |m| "Nice to meet you #{m[1]}!" }
server.run
end
server = Server.new
server.handle(/hello/i){ "Helllo from server at #{Time.now}" }
server.handle(/goodbye/i){ "Goodbye from server at #{Time.now}" }
server.handle(/name is (\w+)/){ |m| "Nice to meet you #{m[1]}!" }
server.run
#这段代码可以简化为以下版本
Server.run do
handle(/hello/i){ "Helllo from server at #{Time.now}" }
handle(/goodbye/i){ "Goodbye from server at #{Time.now}" }
handle(/name is (\w+)/){ |m| "Nice to meet you #{m[1]}!" }
end
#class Server修改如下
class Server
#other methods same as before
#声明为类方法
def self.run(port=3333, &block)
server = Server.new(port)
#使用instance_eval和&block来重构代码
server.instance_eval(&block)
server.run
end
end
include Enumarable