某所で初心者向けRailsコースを受け持っているので、生徒さん向けのメモを書き置きします。
- 簡単なブログアプリ
- モデルは
Post
とAuthor
のみ
- モデルは
-
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)をもたせる
- コントローラー
- モデルの共通処理を操作する
- ビュー
- モデルが作ったデータを参照し、ビジュアライズする