Occasionally when writing Ruby I find myself wanting a pipe
method, similar to tap
but returning the result of calling the block with
Ruby 2.5 introduced Object.yield_self which is exactly the pipe operator you're using: it receives a block, passes self as the first argument to it and returns the result of evaluating the block.
class Object
def yield_self(*args)
yield(self, *args)
end
end
Example usage:
"Hello".yield_self { |str| str + " World" }
# Returns "Hello World"
You can also read a little more about it in the following blog posts:
Here's the the technique I use to chain objects. It's pretty much exactly as above except I don't reopen the Object
class. Instead, I create a Module
which I will use to extend whatever object instance I'm working with. See below:
module Chainable
def as
(yield self.dup).extend(Chainable)
end
end
I've defined this method to prohibit mutative methods from altering the original object. Below is a trivial example of using this module:
[3] pry(main)> m = 'hi'
=> "hi"
[4] pry(main)> m.extend(Chainable).as { |m| m << '!' }.as { |m| m+'?'}
=> "hi!?"
[5] pry(main)> m
=> "hi"
If anybody sees anything wrong with this code, please let me know! Hope this helps.
This abstraction doesn't exist in the core. I usually call it as
, it's short and declarative:
class Object
def as
yield(self)
end
end
"3".to_i.as { |x| x*x } #=> 9
Raganwald usually mentions that abstraction in his posts, he calls it into.
So, summing it up, some names: pipe
, as
, into
, peg
, thru
.