どーもへっぽこです。
コントローラーって便利ですよね、ルーティングしてアクション呼び出すだけでその中の処理を走らせることができる。
ついつい便利で・・
def A
a = 3
b = 2
c = a + b
return c
end
def B
a = 4
b = 2
c = a + b
return c
end
def C
a = 7
b = 6
c = a + b
return c
end
def D
a = 1
b = 9
c = a + b
return c
end
def E
a = 6
b = 2
c = a + b
return c
end
...
たくさんコードを書いてしまう。。
しかし、こんなコントローラーのことをなんと呼ぶか知ってますか?
ファットコントローラーです!
たくさんのコードで肥やせてしまったコントローラーのことを指すんですね。
さてクイズです、ファットコントローラーは悪いでしょうかそうでないでしょうか?
答えは・・
です!
え、なんで。。
そう思った方!コントローラーの役割を考えてみましょう。
図で表すとこちらです。
出典:エンジニアファースト
見てわかる通り、コントローラーはブラウザーからリクエスト(身近なものでいくとURLでアクセスする)を受け取って、モデルでデータもらって、ビューにそれを渡して、ブラウザにレスポンスを返すのが役割ですね。
つまりコントローラーは・・・
リクエストを受け取って返すだけのために存在しているのです!!!
図でわかる通り、データのやりとりはモデルがしています。
お兄さん、こんなコードをコントローラーで書いたことありませんか?
def index
user = User.all
return user
end
def index
user = User.all
return user
end
実際コントローラーがモデルの役割を担ってしまってる。
だって、User.all
でデータベースにアクセスしてデータ取ってきてるじゃん。
さて寄り道も終わり。
つまりなんでファットコントローラーになってしまうかというと
『本来モデルに書かないといけないところをコントローラーに書いている』
これに尽きます。
じゃあどうすればいいの?
答えは超簡単、モデルに書けばいいだけですね。
以下のようにしてコントローラーからモデルに書いた処理を呼び出せます。
#コントローラー
def index
user = User.get_user
return user
end
#モデル
def self.get_user
user = User.all
return user
end
このコードはさっき出てきた↓のコードと同義です。
def index
user = User.all
return user
end
簡単に説明すると、モデルで def self.○○
で定義しておくとコントローラーで モデル名.○○
という形でモデル内で定義したメソッドを呼び出せます。
self
の部分がモデル名にあたるので、User
というモデル名だったらUser.○○
、Project
というモデル名だったらProject.○○
という形になりますね。
○○
の部分はメソッド名、今回はget_user
というメソッド名だったので、User.get_user
で
user = User.all
return user
↑の処理を呼び出せましたね。
賢いお兄さんならわかったかな?
はいそうです、コントローラーの中身はほとんど書く必要がありません。
ほとんど
def index
#モデルの処理を呼び出す
return 〇〇
end
という形で終わらせることができます。
これを守っていればファットコントローラーになりようがありませんね。
ちょっと発展
モデルに処理を寄せる時、なんでもかんでも処理をまとめることは危険です。
重要なのは
共通化を意識することです。
例えばこんなコードがコントローラーに書かれていたとします。
def projects_data
rewards = Reward.all #ドロップダウンで使用するデータ
locations = Location.all #ドロップダウンで使用するデータ
stations = Station.all #ドロップダウンで使用するデータ
terms = Term.all #ドロップダウンで使用するデータ
skills = Skill.all #トランスファーリストで使用するデータ
os = OperatingSystem.all #トランスファーリストで使用するデータ
db = Database.all #トランスファーリストで使用するデータ
position = Position.all #トランスファーリストで使用するデータ
characteristic = Characteristic.all #トランスファーリストで使用するデータ
tool = Tool.all #トランスファーリストで使用するデータ
end
ドロップダウンは↓で
トランスファーリストは↓
です。
つまり、コメントが書かれたデータはそこでしか使われないという意味です。
このコードをモデルに以下のようにまとめたとします。
def self.get_projects_data
rewards = Reward.all
locations = Location.all
stations = Station.all
terms = Term.all
skills = Skill.all
os = OperatingSystem.all
db = Database.all
position = Position.all
characteristic = Characteristic.all
tool = Tool.all
return rewards,locations,stations,terms,skills,os,db,position,characteristic,tool
end
見ての通り、これだとprojects_data
のアクションでしか呼び出せない汎用性のないメソッドとなってしまいます。
そこでモデルを以下のように変更します。
def self.drop_down
rewards = Reward.all
locations = Location.all
stations = Station.all
terms = Term.all
return rewards, locations, stations, terms
end
def self.transferlist
skills = Skill.all
os = OperatingSystem.all
db = Database.all
position = Position.all
characteristic = Characteristic.all
tool = Tool.all
return [
skills,
os,
db,
position,
characteristic,
tool
]
end
これであればprojects_data
以外のアクションでも、ドロップダウンとトランスファーリストを使いたいアクションで個別に呼び出すことができますね。
とても汎用的です。
つまり、処理はモデルに寄せつつその処理は細かく分散していった方が汎用的になりやすいということです。
なので、モデルに処理を寄せる時は共通化する意識を持ちましょう!
以上、へっぽこでした。