What is yield self in Ruby
A question that arises almost every week on #ruby-lang is this:
I know how to create code blocks for my methods, but what is this yield self
?
After trying to explain it every time, I started to use this gist. And now I’m writing a blog post about it. Yeah, it’s that recurrent.
I’m going to assume you know what a code block is - a piece of code that receives an |argument|
as parameter and does some computation, like in Array#each
or String#each_line
. But iterators like these aren’t the only use for them.
In my post about IO in Ruby, I showed how File::open
accepts a code block:
File.open("_posts/2012-10-03-what-is-yield-self-in-ruby.md", 'r') do |file|
puts file
end
# => #<File:0x007fa141185878>
As you can see, the file
variable is in fact the opened object inside the block. After calling the code block, file.close is called before passing control back to your code, avoiding “Oh, I forgot to close this file” kind of errors. (the operating system won’t let you open more files if you don’t close the ones you already used)
Let’s create the Pokemon
class:
class Pokemon
def initialize(move)
@move = move
end
def battle
yield self
end
def use_move
puts "used #{@move}!"
end
end
mewtwo = Pokemon.new "Psychic"
mewtwo.battle do |m2|
m2.use_move
end
# => used Psychic!
arceus = Pokemon.new "Judgement"
arceus.battle do |arc|
arc.use_move
end
# => used Judgement!
As you can see, inside the code block you can call the method use_move
on the argument passed to it. This means that when you call yield self
inside your method, you’re passing the object as a parameter.
It’s a parameter like any other object. And why is this useful? Well, house-keeping like calling a method after the block, but before control is returned to the program (logging is a nice example) and configuration, like in ActiveRecord
.
class CreateProducts < ActiveRecord::Migration
def up
create_table :products do |t|
t.string :name
t.text :description
t.timestamps
end
end
def down
drop_table :products
end
end
In this migration, look at the create_table
method, receiving a code block in which t
is a parameter - it’s the table being created. And all the methods called on it - string
, text
, timestamps
- are used to generate columns.
I hope that this blog post helps people understand what yield self
means. Truly.