Ruby Gold 認定試験の Ver 3 の勉強時に学んだことを備忘録として残しておく

[前回までの記事]

環境

  • ruby: 3.1.2

public_send メソッド

Object#public_send メソッドは private メソッドを呼び出せない
private_send メソッドは存在しない ※private メソッドを 呼び出す場合は Object#send or BasicObject#__send__ メソッドを使用する

class PublicTest
  def public_method
    puts 'call public methods'
  end

  private

  def private_method
    puts 'call private methods'
  end
end

test = PublicTest.new
test.public_method
test.private_method

#=> call public methods
#=> public_send.rb:17:in `<main>': private method `private_method' called for #<PublicTest:0x00000001046769e8> (NoMethodError)

#=> test.private_method
#=> Did you mean?  private_methods

begin & rescue でエラークラスを省略した際の動作

class ExceptionTest
  def foo
    begin
      exit
    rescue => e
      puts 'Default Rescue'
    rescue SystemExit => e
      puts 'System Exit'
    ensure
      puts 'Ensure'
    end

    puts 'End'
  end
end

t = ExceptionTest.new
t.foo
#=> System Exit
#=> Ensure
#=> End

定数の書き換え

メソッド内での書き換えは不可

class Foo
  AAA = 'AAA'
  BBB = 'BBB'

  def foo
    puts AAA
  end
end

class Bar < Foo
  def foo
    AAA = 'aaa'

    puts AAA
  end
end

b = Bar.new
b.foo
#=> modified_constants.rb:12: dynamic constant assignment
#=> AAA = 'aaa'

メソッド外であれば書き換え可能

class Foo
  AAA = 'AAA'
  BBB = 'BBB'

  def foo
    puts AAA
  end
end

class Buzz < Foo
  AAA = 'aaa'

  def foo
    puts AAA
  end
end

b = Buzz.new
b.foo
#=> aaa

同クラス内で定義している場合は warning が発生する ※freeze している/していない 関係なく

class Hoge
  AAA = 'AAA'.freeze

  def foo
    puts AAA
  end
end

class Fuga < Hoge
  AAA = 'aaa'.freeze
  AAA = 'bbb'

  def foo
    puts AAA
  end
end

f = Fuga.new
f.foo
#=> modified_constants.rb:11: warning: already initialized constant Fuga::AAA
#=> modified_constants.rb:10: warning: previous definition of AAA was here
#=> bbb

filter_map メソッド

p [1.34, -1.49, 2.7].filter_map {|n| n.round if 0 < n } # これがリファレンスにも乗っているパターン
#=> [1, 3]
p [1.34, -1.49, 2.7].filter_map {|n| 0 < n && n.round } # 上と同じ結果
#=> [1, 3]
p [1.34, -1.49, 2.7].filter_map {|n| 0 < n }
#=> [true, true]
p [1.34, -1.49, 2.7].filter_map {|n| 0 < n || n.round }
#=> [true, -1, true]