LoginSignup
0
0

【Rails】コントローラーにたくさんコードを書いてしまった・・・そんな時はモデルに処理を寄せよう!

Last updated at Posted at 2022-06-15

どーもへっぽこです。
コントローラーって便利ですよね、ルーティングしてアクション呼び出すだけでその中の処理を走らせることができる。
ついつい便利で・・

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
...

たくさんコードを書いてしまう。。
しかし、こんなコントローラーのことをなんと呼ぶか知ってますか?
topics_46_4.jpeg
ファットコントローラーです!
たくさんのコードで肥やせてしまったコントローラーのことを指すんですね。
さてクイズです、ファットコントローラーは悪いでしょうかそうでないでしょうか?
答えは・・
1182533.png
です!
え、なんで。。
そう思った方!コントローラーの役割を考えてみましょう。
図で表すとこちらです。
スクリーンショット_2022-06-15_17_21_01.png
出典:エンジニアファースト
見てわかる通り、コントローラーはブラウザーからリクエスト(身近なものでいくとURLでアクセスする)を受け取って、モデルでデータもらって、ビューにそれを渡して、ブラウザにレスポンスを返すのが役割ですね。
つまりコントローラーは・・・
リクエストを受け取って返すだけのために存在しているのです!!!
図でわかる通り、データのやりとりはモデルがしています。
お兄さん、こんなコードをコントローラーで書いたことありませんか?

def index
  user = User.all
  return user
end

でも図ではこうなってるでしょ?
スクリーンショット_2022-06-15_17_21_01.png
でも↓のコードは

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

ドロップダウンは↓で
スクリーンショット 2022-06-15 18.05.27.png
トランスファーリストは↓
スクリーンショット 2022-06-15 18.06.45.png
です。
つまり、コメントが書かれたデータはそこでしか使われないという意味です。
このコードをモデルに以下のようにまとめたとします。

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以外のアクションでも、ドロップダウンとトランスファーリストを使いたいアクションで個別に呼び出すことができますね。
とても汎用的です。
つまり、処理はモデルに寄せつつその処理は細かく分散していった方が汎用的になりやすいということです。
なので、モデルに処理を寄せる時は共通化する意識を持ちましょう!
以上、へっぽこでした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0