当サイトの記事を別媒体に流用する際は必ず問い合わせページからご連絡下さい

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

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

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

なので、モデルに処理を寄せる時は共通化する意識を持ちましょう!
以上、へっぽこでした。

ワンクリックでランキングに協力してください(´;ω;`)
※万一記事に関わる個人・団体の方で記事の削除依頼がある場合、本サイトのお問い合わせから連絡ください。内容を確認させていただきます。

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)