a5iuoのブログ

システムを運用することが好きな人間のブログです。

【Ruby】ぼっち演算子が便利ですね

ぼっち演算子とは

xxx&.yyy

safe navigation operator(通称「ぼっち演算子」)。xxx が nil でないときにメソッドyyyを呼び出す。メソッド呼び出し(super・ブロック付き・yield) を参照。

Rubyで使われる記号の意味(正規表現の複雑な記号は除く) (Ruby 3.3 リファレンスマニュアル)

メソッド呼び出しで `.' の代わりに `&.' を使うことができます。この形式でメソッドを呼びだそうとすると、レシーバが nil の場合は以下のように働きます。

  • 引数の評価が行なわれない
  • メソッド呼び出しが行われない
  • nil を返す

レシーバが nil でない場合は通常のメソッド呼び出しが行われます。

メソッド呼び出し(super・ブロック付き・yield) (Ruby 3.3 リファレンスマニュアル)

irbで確認


irb(main):001:1* class Friend
irb(main):002:1*   attr_accessor :name, :age, :score
irb(main):003:2*   def initialize(name, age, score=nil)
irb(main):004:2*     @name = name
irb(main):005:2*     @age = age
irb(main):006:2*     @score = score
irb(main):007:1*   end
irb(main):008:0> end
=> :initialize

irb(main):009:0> user = Friend.new('Bob', 24, 80)
=> #<friend:0x0000019ec42128e8 age="24," name="Bob" score="80">

# scoreが入力されている時のみ、文言を表示したい
# Railsアプリなら、ビューに書く想定(その際はblank?を使う)

irb(main):010:0> puts "#{user.name}は#{user.score}点です。" if !user.score.nil?
Bobは80点です。
=> nil

irb(main):011:0> user.score = nil
=> nil
# 文言を表示しない、期待通り
irb(main):012:0> puts "#{user.name}は#{user.score}点です。" if !user.score.nil?
=> nil

# userが何らかの理由でnil
# Railsアプリなら、コントローラでuser = User.where(name: 'hoge')のような処理をしていて、ヒットしなかったときなど
irb(main):013:0> user = nil
=> nil

# NilClassのscoreメソッドなんて無いよ!と怒られる
# Railsアプリなら、ビューのレンダリングに失敗する(「画面見れません!」と利用者から怒られる)
irb(main):014:0> puts "#{user.name}は#{user.score}点です。" if !user.score.nil?
(irb):14:in `<main>': undefined method `score' for nil:NilClass (NoMethodError)
        from C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/irb-1.6.2/exe/irb:11:in `<top (required)>'
        from C:/Ruby32-x64/bin/irb:33:in `load'
        from C:/Ruby32-x64/bin/irb:33:in `<main>'
        
# ぼっち演算子で回避
irb(main):015:0> puts "#{user.name}は#{user.score}点です。" if !user&.score.nil?
=> nil

# defined?で回避する手もある
irb(main):016:0> puts "#{user.name}は#{user.score}点です。" if defined?(!user.score.nil?)
=> nil