何も考えずにやりたいように記述していると増えていくコード量、下がる可読性……
なるべく簡潔に纏められるよう、MVCそれぞれで使える手段を初学者なりにまとめました。
MVCの役割をおさらい
MVC | 役割 |
---|---|
Model | アプリケーションで扱うデータの操作/加工 |
View | ユーザへの情報表示、ユーザからの入力の受け取り |
Controller | ModelやViewとの情報のやり取りをする |
この役割を理解し、それぞれの役割に相応しい処理を記述していく。 | |
役割を考えず好きに各ファイルに記述していると、メンテナンスも難しくなってきてしまう。 | |
例えば、Modelに記述すべき処理をControllerに記述してしまうとFat Controller | |
(コードが大量に書かれて膨れ上がったController)になるなどの問題が発生しやすくなる。 |
Controllerのコード量を減らす方法
Modelに記述する。
上記のMVCの各役割を考えて、データの処理・加工を担うメソッドはModelに記述する。
訂正前
class PostsController < ApplicationController
def index
@posts = Post.order(created_at: :desc).limit(10)
end
end
訂正後(Modelに移動)
Modelクラスに対して直接呼び出せるようクラスメソッドとして定義。
class Post < ApplicationRecord
def self.latest(number)
order(created_at: :desc).limit(number)
end
end
Controllerでメソッドを呼び出す
class PostsController < ApplicationController
def index
@posts = Post.latest(10)
end
end
クラスメソッドでなく、scopeを使うことも出来る。
class Post < ApplicationRecord
scope :latest, -> (number = 10){order(created_at: :desc).limit(number)}
end
class PostsController < ApplicationController
def index
@posts = Post.latest
end
end
Modelのコード量を減らす方法
Concernを使う
複数のModelに同じ処理が繰り返し記述されている場合などに、Concernを使って共通処理を切り出すことが出来る。
scope :latest, -> (number = 10){order(created_at: :desc).limit(number)}
def hoge
puts "hogehoge"
end
scope :latest, -> (number = 10){order(created_at: :desc).limit(number)}
def hoge
puts "hogehoge"
end
app/models/concernsにファイルを作成・共通処理を記述。
module CommonModule
extend ActiveSupport::Concern
included do
scope :latest, -> (number = 10){order(created_at: :desc).limit(number)}
def self.hoge
puts "hogehoge"
end
end
end
各Modelでincludeすることで共通処理が使用できる。
include CommonModule
include CommonModule
バリデーションを切り出す
長くなりがちなバリデーションの記述をvalidatorに切り出すことが出来る。
appディレクトリ下にvalidatorsディレクトリを作成し、バリデーション用のファイルを作成する。
class PostValidator < ActiveModel::Validator
def validate(record)
prohibited_words = ["baka","aho"]
if prohibited_words.any?{ |word| record.content.include?(word) }
record.errors.add(:content, "禁止ワードが含まれています。")
end
end
end
Model側に追加で記述する。
validates_with PostValidator
コールバックを切り出す
コールバックもModelから切り出すことが出来る。
app/callbacksディレクトリを作成し、コールバック用のファイルを作成する。
(クラス名はコールバック名と同じにすること)
class PostCallback
def before_create(post)
post.title = "No Title" if post.title.blank?
end
end
Model側に追加で記述する。
before_create PostCallback.new