おーしまブログ

プログラミングやってます

<rails> superメソッドとは

こんにちは、おーしまです。

今日は、自動車レビューサイトのコメント機能を実装しましたが、特に新しく得られた技術はないので、前回の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

実行結果
f:id:tomo_bb_aki0118115:20201031234953p:plain

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)なしでも実行してみましたが、
実行できませんでした。


いや〜、勉強になりました。



今回はここまでです。
それでは、また〜

ここはどこ おれはだれ それに近いものがあんだよ 始めようとした奴らも迷い始めてる 怖がらせないでよ そりゃ甘くはないけど まだまだ 夢見ていい世界なんでしょ {UVERwould「ハイ!問題作」}