バートリーのさいとうです。
今回は
カラムがメソッドのように使えるのはなぜ?
ということについて解説していきます。
早速ですが、railsのerbファイルなどで、このようなコードを見たことありませんか?
<%= user.name %>
=> userのnameカラムの値(例:”Taro” など)が出力される。
僕はこれまで、なんだか違和感を感じながらこれを利用してきました。
なぜなら、メソッドが似たような使われ方をしていたからです。
class User
def initialize(name)
@name = name
end
def display_name
p @name
end
end
user = User.new("Taro")
user.display_name
# => "Taro"
ここでまず一つ誤解が生まれそうなので、補足しておくと
メソッドがカラムの真似をしているのではなく、メソッドの使い方をカラムが真似しています。
では、なぜrailsでは真似っこができるのでしょうか?(他の言語はわかりません)
この理由を
- ActiveRecordを継承したクラス(モデル)が自動的にやっていること
- ↑のクラスがもたらしてくれる恩恵
- もう一度例を見て確認
という3つのパートにわけて、Rails ガイドを参考に最高にわかりやすく解説します。
筆者は
- 4月からエンジニアとして働き始めた駆け出しエンジニア
→駆け出しならではの、目線で初歩から説明できる - アウトプット経験豊富(noteで120本以上の記事を執筆 https://note.com/youcan08)
→わかりやすく、読みやすい文章構成が得意
ですので、特に未経験からエンジニアになった方などは、この記事を読んでrailsへの理解を深めていってください。
ActiveRecordを継承したクラスが自動的にやっていること
自動的にやっていることは、以下の二つです。
- ActiveRecordを継承したクラス(モデル)は、モデルとモデル名の複数形のテーブルがマッピングされる。
- さらに、テーブルのカラムの各行を、そのモデルから生成されるインスタンスの属性としてマッピングする。
これだけだと、??だと思うので、実例を交えながら紐解いていきましょう。
ActiveRecordを継承したクラス(モデル)は、モデルとモデル名の複数形のテーブルがマッピングされる。
ActiveRecordを継承したクラスは、MVCの中でM=モデルとして利用されるクラスになります。
今回は、Userモデルを例に取ります。
class User < ActiveRecord
end
そして、このUserモデルは自動的に、モデル名の複数形のテーブルにマッピングされます。
マッピングとは、日本語で「関連づけられる」という意味です。
つまり、言い換えると「Userモデルとusersテーブルが関連付けられる」という意味となります。紐付けられるという言葉でもほぼ同義です。
テーブルのカラムの各行を、そのモデルから生成されるインスタンスの属性としてマッピングする。
さらに、先ほどUserモデルに関連付けが行われたusersテーブルのカラムが、Userモデルのインスタンスの属性としてマッピングされます。
マッピングは先ほども出てきたように、「関連付けられる」という意味です。
さらに今回は、属性という言葉が出てきました。こいつは厄介な言葉です。
属性=プロパティともいいますが、railsでは、インスタンス変数となります。
インスタンス変数とは何でしょうか?
それは、インスタンスが持つ特徴や状態を含む変数です。@がついた変数です。
先ほど出したUserクラスの例で考えると、こうなります。
理解していただけたでしょうか?
もしnameカラムがあれば、同じようなことが起きます。
つまり、クラスがActiveRecordを継承することでモデルとなり、テーブルのカラムをそのモデルから生成されるインスタンスの属性として扱うことができるようになるということです。
さらに詳しく、次の章で見ていきましょう。
ActiveRecordを継承したクラス(=モデル)がもたらしてくれる恩恵
属性やマッピングという言葉が出てきて少し難しく感じた方もいると思いますが、ここからさらに噛み砕いて解説を進めていきますので、頑張ってついてきて下さい。
さて、ActiveRecordを継承したクラス(=モデル)がもたらしてくれる恩恵とは何なのか?この真相に迫っていきます。
早速結論いきます。カラムは自動的に(もちろん見えてはいないけれど!)こういう風にモデルに定義されていることになっています。そのおかげで、ゲッターとセッターという恩恵を受けます。
class User < ActiveRecord
#nameカラムを定義します
def name #ゲッター
@name #"Taro"が入っているとしましょう。
end
def name=(name) #セッター
@name = name
end
end
ゲッター 、セッターという言葉が出てきました。
ゲッター:参照するためのメソッド
ゲッターが定義されるおかげで
<%= user.name %>
=> "Taro"
ということが可能になるのです。つまり、userが持っている@nameを参照したということです。
セッター:編集・更新するためのメソッド
セッターが定義されるおかげで
user = User.new(name: "Taro")
p user.name => "Taro"
user.name = "Taroooooooooo"
p user.name => "Taroooooooooo"
ということが可能になるのです。つまり、user.nameでusersテーブルのnameカラムの値が”Taroooooooooo”という文字列に編集・更新されたいうことです。
最初にあげたモヤモヤをもう一度
一番最初にあげた、僕がモヤモヤしていた記述をもう一度提示します。
<%= user.name %>
=> userのnameカラムの値(例:”Taro” など)が出力される。
これが実現するのは、ここまで説明してきた通りであり、まとめると
- ActiveRecordを継承するクラス(モデル)は、そのモデル名の複数形のテーブルと関連付けられ、更にそのモデルから生成されるインスタンスは、テーブルの各行にあるカラムを、属性として持つ
- 属性としてもつこと、それはゲッターとセッターを持つこと。ゲッターは参照のために、セッターは編集更新のために定義される。
- ゲッターもセッターもメソッドなので、カラムの呼び出しはメソッドのように行うことができる。
となります。
まとめ
今回は、カラムがメソッドのように使えるのはなぜ?を解説しました。
少しでも参考になれば嬉しいです。
このように、月に15本目標で、Ruby, Ruby on Railsを中心に技術ブログを更新しています。
もし参考になったなと思ったら、ブックマークをお願い致します。
最後まで読んでいただき、ありがとうございました!
それでは。