こんにちは、おーしまです。
今日は、自動車レビューサイトのコメント機能を実装しましたが、特に新しく得られた技術はないので、前回のsuperメソッドに関して書いていきます。
とりあえず、superメソッドとは?
子クラスのインスタンスに対して、同名の親クラスのメソッドをそのまま呼び出すことが出来るメソッド
例で見ていきましょう。
class Car def ride "自動車に乗ります" end end class Human < Car def ride "免許持ってません" end end class Dog < Car def ride super end end @human = Human.new puts @human.ride @dog = Dog.new puts @dog.ride
実行結果
HumanクラスとDogクラスはCarクラスの子クラスになっています。
Humanクラスのrideメソッドにはsuperが記述してないので、そのまま出力されていますが、Dogクラスのrideメソッドにはsuperが記述してあるので、Carクラスのrideメソッドは呼び出されていますね。
それでは、本題に入っていきましょう。
前回の、自動車レビューサイトのsuper部分のコードです。
class SaveCarsTag include ActiveModel::Model #省略 def initialize(attributes = nil, car: Car.new) @car = car attributes ||= default_attributes super(attributes) end #省略 end
つまりこれでいうなら、SaveCarsTagクラスの親クラスのinitializeメソッドを呼び出しているということになります。
では、SaveCarsTagクラスの親クラスって何?
SaveCarsTag.superclass
で見ることができます。
=>Object
rails では、基本的にモデルの親クラスは全て、このObjectクラスになるようです。
SaveCarsTagクラスも、include ActiveModel::Modelを記述しているので、モデルと同じ扱いになり、親クラスはObjectクラスとなりました。
次に、Objectクラスのinitializeメソッドはというと、、、
リファレンスマニュアルにはこう書いてありました。
class Foo def initialize name puts "initialize Foo" @name = name end end class Bar < Foo def initialize name, pass puts "initialize Bar" super name @pass = pass end end it = Bar.new('myname','0500') p it #=> initialize Bar # initialize Foo # #<Bar:0x2b68f08 @name="myname", @pass="0500">
自動車レビューアプリで言えば、、、
- class Foo の initializeメソッドが、Objectクラスのinitializeメソッド
- class Bar の initializeメソッドが、SaveCarsTagクラスのinitializeメソッド
- 最後の部分の.newがコントローラー
といったところでしょうか。
どうやら引数が、重要なようです。
class SaveCarsTag include ActiveModel::Model #省略 def initialize(attributes = nil, car: Car.new) @car = car attributes ||= default_attributes super(attributes) end #省略 end #コントローラー def update @form = SaveCarsTag.new(car_params, car: @car) end
まずはインスタンスを生成した際に、(car_params, car: @car)を送っています。
なぜかわかりませんが、おそらくこういう感じになっているはずです。
def initialize(attributes = (car_params), car: @car)
さらに、super(attributes)、として引数を指定しているので、objectクラスのinitializeメソッドを呼び出して、@formにそれぞれ値が代入されて帰ってくる。。そういう認識でしょうか。。
あー、書きながら今、わかりました。
そもそもObjectクラスのinitializeメソッドしか、初期値を設定できないので、最初から初期値を入れたい時はsuperでObjectクラスのinitializeを呼び出して、引数で値を入れてあげれば、それが初期値になるということですね!多分。
つまり、initializeを使う時はsuper(値)って書いておけば、値を全部入れてくれるよってことだと思います。
理解できたでしょうか?
試しに、superなしや、(attributes)なしでも実行してみましたが、
実行できませんでした。
いや〜、勉強になりました。
今回はここまでです。
それでは、また〜