LoginSignup
45
46

More than 5 years have passed since last update.

Skinny Controller, Fat Modelの簡単な例

Last updated at Posted at 2015-06-15

某所で初心者向けRailsコースを受け持っているので、生徒さん向けのメモを書き置きします。

  • 簡単なブログアプリ
    • モデルはPostAuthorのみ
  • app/views/posts/index.erbに、最新記事を5件表示させることが課題

Skinny Controller, Fat Modelとは(ざっくり)

  • 薄いコントローラー、厚いモデル
  • データ加工処理はモデルに担当させる
  • コントローラーをシンプルにする
    • 処理の流れがわかりやすくなる

Viewのみで最新記事表示を実装した場合

  • 一番原始的なパターンです。

実装方法

app/controllers/posts_controller.rb
def index
  @posts = Post.all
end
app/views/posts/index.erb
<% @posts.reverse.each_with_index do |post, index| %>
  <%# 6個目以上の記事の場合はBreak %>
  <% if index >= 5
       break
     end
  %>
  <%= link_to post.title, post_path(post) %>
<% end %>

問題点

  • indexのViewが汚れる
  • 仕様変更によって最新記事が他のビュー(ex.posts/show.html.erb)でも必要になったら、また書く必要がある

Controllerが加工処理を受け持った場合

実装方法

app/controllers/posts_controller.rb
def index
  # クエリメソッドで降順並び替え&5件までの呼び出しとしている
  @posts = Post.order(created_at: :desc).limit(5)
end
app/views/posts/index.erb
<% @posts.each do |post| %>
  <%= link_to post.title, post_path(post) %>
<% end %>

問題点

  • 他のアクションやコントローラで最新5件の@postsが必要となった場合、コードが重複する(見通しが悪くなる)
  • 最新記事が5件→10件に仕様変更となったら、すべて書き換えとなってしまう
  • コントローラーで「データ加工」はしちゃいけない

Modelが加工処理を受け持った場合

  • こっちがSkinny Controller, Fat Modelのパターン

実装方法

app/models/post.rb
class Post < ActiveRecord::Base
  scope :latest, -> (limit = 5) { order(created_at: :desc).limit(limit) }
end
app/controllers/posts_controller.rb
def index
  # Modelのscopeを利用する
  @posts = Post.latest
end
app/views/posts/index.erb
<% @posts.each do |post| %>
  <%= link_to post.title, post_path(post) %>
<% end %>

まとめ

  • モデル
    • 共通処理(scope)をもたせる
  • コントローラー
    • モデルの共通処理を操作する
  • ビュー
    • モデルが作ったデータを参照し、ビジュアライズする
45
46
1

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
45
46