blockの利用例 Ruby

こんにちは。ikedaです。
以前ご紹介したgem Faradayの実装例で、blockを解説することがあったのですが
blockを利用した書き方について触れていなかったので書いていきたいと思います。完全に小ネタです。

blockの書き方ですが、引数にblock宣言することと、yieldを利用する2通りあります。

ブロックを引数で持つ場合

  class Hoge
    def initialize(&block)
      block.call
    end
  end

  Hoge.new do
    p "Hello"
  end
  # => "Hello"
  # => #<Hoge:0x007ff4f480cca8>
  
  Hoge.new { p "Hello" } # 上記と同じ意味です。
  # => "Hello"
  # => #<Hoge:0x007ff4f480cca8>

  Hoge.new # ブロックを渡していないのでエラー
  # => NoMethodError: undefined method `call' for nil:NilClass

引数として持たない場合

class Fuga
  def initialize()
    yield(self) if block_given?
    # block_given?でブロックが与えられているか調べる
  end
end

Fuga.new do |fuga|
  fuga.class
end 
# => #<Fuga:0x007ff4f4160c60>

Fuga.new { self.class }
# => #<Fuga:0x007ff50b29e340>

Fuga.new
# => #<Fuga:0x007ff4f4153c18>

上記で書いている通りyieldにインスタンスを引数に渡して返すこともできるので次のような書き方ができます。

*block_given?について詳しくはこちらへ

ブロック利用例

class Person
  attr_accessor :name, :age, :job

  def initialize(&block)
    yield(self) if block_given?
  end
end

person = Person.new do |per|
  per.name = "ikeda"
  per.age = 99
  per.job = "engineer"
end

puts person.name
# => "ikeda" 
puts person.age
# => 99
puts person.job
# => "engineer"

selfが自分自身を指しているのでインスタンスを返却してブロック内で値をセットしています。

gem Faradayでも使われていて、そちらではstructと合わせて実装されていますね。

[おまけ]instance_evalを利用したblockの記述

class Person
  attr_accessor :name

  def intialize()
    yield(self) if block_given?
  end

private
  def fuga
    puts "Hi, I'm #{name.nil? ? "piyo" : self.name}."
  end
end

Person.new.instance_eval { fuga }
# => Hi, I'm piyo.

Person.new.instance_eval do
  fuga
end # こちらも同じ意味です。
# => Hi, I'm piyo.

Person.new do |per|
  per.name = "neko"
  per.instance_eval { fuga }
end
# => Hi, I'm neko.

以上です。

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

ikeda

業務系のエンジニアから2013年Web系エンジニアに転身して、2014年02月よりBPS株式会社に入社。

ikedaの書いた記事

開発
静的解析ツールgem RuboCop

2014年09月11日

開発
jsCafe#20に参加してきました

2014年05月17日

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ