Tech Racho エンジニアの「?」を「!」に。
  • 開発

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.

以上です。


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。