Ruby Blocks
Ruby has a concept of Block.
- A block consists of chunks of code.
- You assign a name to a block.
- The code in the block is always enclosed within braces
{}
. - A block is always invoked from a function with the same name as that of the block. This means that if you have a block with the name test, then you use the function test to invoke this block.
- You invoke a block by using the
yield
statement.
1 |
block_name { |
The yield Statement
yield
is a statement in ruby that is widely used in order to share common logic.
Imagine that you have two huge business logic that is only different from each other in a few couple lines. How to avoid checking in the 95% shared logic twice? You definitely don’t want to write code like the following:
1 |
def |
Wouldn’t it nice to be
1 |
def |
In Java, you can a chieve it either with Java 8 new lambda feature (highly recommended, because it gives you much more flexibility) or executing methods in interface/abstract class defined in both classes (old style before lambda is available).
1 |
public void () { |
How can you achieve this in Ruby? With yield
!
From the name you can tell that, just like yielding to people in a highway traffic, it’s about yielding to an inserted/passed-in statement when program hit this key word. yeild
statement can take either no params or any number of params.
yield with no params
1 |
def test |
Output:
1 |
xxx |
You can see that yield
will be replaced by statement puts "000"
yield with params
Here’s a simple example of yield
taking 1 param
1 |
def test |
1 |
xxx |
The format to rake two params is:
1 |
yield a, b |
and the block is:
1 |
test {|a, b| statement} |
Here’s an example to encrypt and decrypt a yaml file. Most logic is the same between processes of encrypting and decrypting. So we use yield
to abstract that and maintain the common logic in only one copy.
The first version:
1 |
require 'yaml' |
The problem with the first version is that you’ll find your new file doesn’t have all the updated encrypted/decrypted values. The root cause is the valid scope of a yield
statement. In the above example, the updated v
only lives in the line 9 or line 13, and doesn’t last when jumping back to the context in line 22.
The fix is to pass in not only the k-v pair, but also the Hash object itself to make sure the changes persist.
1 |
require 'yaml' |
近期评论