8.6K Views
December 23, 21
スライド概要
https://misokatsu-web.connpass.com/event/198867/
Ruby / Vim / C++
Misokatsu.rb #1 Ruby 3.0 で変わった private と attr_xxx
⾃⼰紹介 名前: osyo Twitter : @pink_bangbi github : osyo-manga ブログ : Secret Garden(Instrumental) 趣味で Ruby にパッチを投げたり気になった bugs.ruby のチケットを ブログにまとめたりしている Kaigi on Rails ActiveRecord の歩み⽅ 銀座これからの Rails Ruby と今の Ruby について 12⽉25⽇にリリースされる Ruby 3.0 に備えよう! Burikaigi2021 Ruby 2.0 から Ruby 3.0 を駆け⾜で振り返る
Misokatsu.rb はワシが名付けたんじゃよ
Ruby 3.0 今⽇話すこと で変わった private と attr_xxx
public / private / protected のおさらい はメソッドのアクセス参照を制御する機能 にするとレシーバを付けてメソッドが呼べなくしたり等 public / private / protected private class X # Ruby 3.0 def hoge = "hoge" これは で⼊ったエンドレスメソッド定義 引数の名前のメソッドを # private :hoge private 化する レシーバを付けない場合は呼び出せる # def foo = hoge end 化されたメソッドはレシーバ付きで呼べない # private x = X.new p x.foo # error: private method `hoge' called for #<X:0x0000562a3e262460> (NoMethodError) x.hoge
Ruby 3.0 の public / private / protected について では private などの引数に配列を渡せるようになった 元々複数の引数を渡すこともできたが配列も渡せるようになった Ruby 3.0 class def def def X hoge = "hoge" foo = "foo" bar = "bar" 配列を渡して複数のメソッドを 化できる 以下のように可変⻑引数で書くことは以前からできてた # private # # private :hoge, :foo, :bar private [:hoge, :foo, :bar] end pp X.private_instance_methods(false) # => [:hoge, :foo, :bar]
attr_accessor / attr_reader / attr_writer attr_accessor / attr_reader / attr_writer するメソッド class User # #id attr_reader :id ゲッターメソッド セッターメソッド アクセッサメソッド メソッドが定義される # #age, #age= attr_accessor :age end homu = User.new homu.name = "homu" homu.age = 14 # homu.id = 1 これはエラーになる はアクセッサメソッドを定義 メソッドが定義される # #name= attr_writer :name のおさらい メソッドが定義される
Ruby 3.0 の attr_accessor / attr_reader / attr_writer では attr_accessor などの戻り値が『定義されたメソッドの 配列』を返すようになった Ruby 3.0 class User # pp attr_reader :id, :status # => [:id, :status] ゲッターメソッド名が返ってくる セッターメソッド名が返ってくる # pp attr_writer :name # => [:name=] ゲッターとセッターの両⽅のメソッドが返ってくる # pp attr_accessor :age, :type # => [:age, :age=, :type, :type=] end
Ruby 3.0 で private と attr_accessor を 組み合わせると…?
と attr_accessor を ワンラインで適⽤できる private
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=]
おまけ:クラスメソッドを private 化する スコープ内ではインスタンスメソッドを private 化する クラスメソッドを private 化する場合は特異クラスをオープンする class class X # def self.hoge = "hoge" クラスメソッドを定義する これはインスタンスメソッドを # private :hoge private 化するのでエラーになる 特異クラスをオープンしてその中で private 化する ここは クラスの特異クラスのスコープになるので クラスの特異クラスのメソッドがプライベート化される # class <<self # X # X private :hoge end end # error: private method `hoge' called for X:Class (NoMethodError) X.hoge
以下のように 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]
まとめ
まとめ から の引数や attr_accessor の戻り値が少し変わった はメソッド名を配列で受け取ることができるようになった は定義されたメソッド名を配列を返すようになった 少し変わっただけでめっちゃ便利に使えるようになった private + attr_accessor はかなり前から要望が来ていたのでやっと流 ⾏った機能 古くは 2012年の頃からチケットが⽴っていた [Feature #6198] public/protected/private with attr_* ⼀応⾮互換な変更ではあるので注意してね!!! Ruby 3.0 private private attr_accessor
参照 [Feature #17314] Provide a way to declare visibility of attributes defined by attr* methods in a single expression
ご清聴 ありがとうございました