Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby 3.0 で変わった private と attr_xxx

osyo
February 22, 2021

Ruby 3.0 で変わった private と attr_xxx

osyo

February 22, 2021
Tweet

More Decks by osyo

Other Decks in Programming

Transcript

  1. ⾃⼰紹介 ⾃⼰紹介 名前:osyo Twitter : github : ブログ : 趣味で

    Ruby にパッチを投げたり気になった bugs.ruby のチケットを ブログにまとめたりしている Kaigi on Rails 銀座Rails Burikaigi2021 @pink_bangbi osyo-manga Secret Garden(Instrumental) ActiveRecord の歩み⽅ これからの Ruby と今の Ruby について 12 ⽉25 ⽇にリリースされる Ruby 3.0 に備えよう! Ruby 2.0 から Ruby 3.0 を駆け⾜で振り返る
  2. public / private / protected のおさらい public / private /

    protected のおさらい public / private / protected はメソッドのアクセス参照を制御する機能 private にするとレシーバを付けてメソッドが呼べなくしたり等 class X # これは Ruby 3.0 で⼊ったエンドレスメソッド定義 def hoge = "hoge" # 引数の名前のメソッドを private 化する private :hoge # レシーバを付けない場合は呼び出せる def foo = hoge end # private 化されたメソッドはレシーバ付きで呼べない x = X.new p x.foo # error: private method `hoge' called for #<X:0x0000562a3e262460> (NoMethodError) x.hoge
  3. Ruby 3.0 の public / private / protected について Ruby

    3.0 の public / private / protected について Ruby 3.0 では private などの引数に配列を渡せるようになった 元々複数の引数を渡すこともできたが配列も渡せるようになった class X def hoge = "hoge" def foo = "foo" def bar = "bar" # 配列を渡して複数のメソッドを private 化できる # 以下のように可変⻑引数で書くことは以前からできてた # private :hoge, :foo, :bar private [:hoge, :foo, :bar] end pp X.private_instance_methods(false) # => [:hoge, :foo, :bar]
  4. attr_accessor / attr_reader / attr_writer のおさらい attr_accessor / attr_reader /

    attr_writer のおさらい attr_accessor / attr_reader / attr_writer はアクセッサメソッドを定義 するメソッド class User # ゲッターメソッド #id メソッドが定義される attr_reader :id # セッターメソッド #name= メソッドが定義される attr_writer :name # アクセッサメソッド #age, #age= メソッドが定義される attr_accessor :age end homu = User.new homu.name = "homu" homu.age = 14 # これはエラーになる homu.id = 1
  5. Ruby 3.0 の attr_accessor / attr_reader / attr_writer Ruby 3.0

    の attr_accessor / attr_reader / attr_writer Ruby 3.0 では attr_accessor などの戻り値が『定義されたメソッドの 配列』を返すようになった class User # ゲッターメソッド名が返ってくる pp attr_reader :id, :status # => [:id, :status] # セッターメソッド名が返ってくる pp attr_writer :name # => [:name=] # ゲッターとセッターの両⽅のメソッドが返ってくる pp attr_accessor :age, :type # => [:age, :age=, :type, :type=] end
  6. Ruby 3.0 で private と attr_accessor を Ruby 3.0 で

    private と attr_accessor を 組み合わせると… ? 組み合わせると… ?
  7. private attr_accessor :hoge, :foo と定義できる private attr_accessor :hoge, :foo と定義できる

    private は配列を受け取ることができる attr_accessor は配列を返す この2 つを組み合わせることでワンラインで完結することができる class User # attr_reader の結果を public 化する public attr_reader :id # attr_reader の結果を private 化する private attr_writer :name # attr_accessor すべてを private 化する private attr_accessor :age, :type end pp User.private_instance_methods(false) # => [:age, :name=, :type, :type=, :age=]
  8. おまけ:クラスメソッドを private 化する おまけ:クラスメソッドを private 化する class スコープ内ではインスタンスメソッドを private 化する

    クラスメソッドを private 化する場合は特異クラスをオープンする class X # クラスメソッドを定義する def self.hoge = "hoge" # これはインスタンスメソッドを private 化するのでエラーになる private :hoge # 特異クラスをオープンしてその中で private 化する class <<self # ここは X クラスの特異クラスのスコープになるので # X クラスの特異クラスのメソッドがプライベート化される private :hoge end end # error: private method `hoge' called for X:Class (NoMethodError) X.hoge
  9. 以下のように attr_accessor も特異クラスのスコープで定義できる class X class <<self # X の特異クラスに対してメソッドを定義する

    # すなわちクラスメソッドとしてメソッドが定義される private attr_accessor :hoge, :foo, :bar end end pp X.private_methods(false) # => [:hoge, :foo, :foo=, :bar, :bar=, :hoge=, :initialize, :inherited]
  10. まとめ まとめ Ruby 3.0 から private の引数や attr_accessor の戻り値が少し変わった private

    はメソッド名を配列で受け取ることができるようになった attr_accessor は定義されたメソッド名を配列を返すようになった 少し変わっただけでめっちゃ便利に使えるようになった private + attr_accessor はかなり前から要望が来ていたのでやっと流 ⾏った機能 古くは 2012 年の頃からチケットが⽴っていた ⼀応⾮互換な変更ではあるので注意してね!!! [Feature #6198] public/protected/private with attr_*
  11. 参照 参照 [Feature #17314] Provide a way to declare visibility

    of attributes defined by attr* methods in a single expression