Elixir-like pipes in Ruby
If you use Elixir (and the Phoenix framework), you’ve probably admired the beauty and power of the |> pipelines. For example:
"String"
|> add(" is a common type")
|> IO.puts
# => "String is a common type"
In Ruby, the same mechanism can be achieved using yield_self:
"String"
.then { |s| s.concat(" is a common type") }
.then { |s| puts s }
The thing I love in Elixir is that you don’t need to pass the previous value explicitly—the put alone knows to take the preceding result as its first argument.
I wanted the same behavior in Ruby.
Or at least to avoid the redundant |subject|.
⚠️ 💣💀😱 To do this, I’m sacrificing the Kernel | operator and using it for my purposes:
module Kernel
def |(&block)
instance_eval(&block)
end
end
Now, I almost get the same magic; I just need to use self to refer to the previous result:
"My string"
.| { "#{self} is a String value" }
.| { puts self }
Preserving the | operator
To avoid permanently overriding |, we can use refinements:
# In a file 'pipeline.rb'
module Pipeline
refine Kernel do
def |(&block)
instance_eval(&block)
end
end
end
Now, to use this feature:
require 'pipeline'
using Pipeline
"My string"
.| { "#{self} is a String value" }
.| { puts self }