LoginSignup
0
0

More than 3 years have passed since last update.

Ruby on Rails MVC周りのリファクタリング方法例まとめ

Posted at

何も考えずにやりたいように記述していると増えていくコード量、下がる可読性……
なるべく簡潔に纏められるよう、MVCそれぞれで使える手段を初学者なりにまとめました。

MVCの役割をおさらい

MVC 役割
Model アプリケーションで扱うデータの操作/加工
View ユーザへの情報表示、ユーザからの入力の受け取り
Controller ModelやViewとの情報のやり取りをする

この役割を理解し、それぞれの役割に相応しい処理を記述していく。
役割を考えず好きに各ファイルに記述していると、メンテナンスも難しくなってきてしまう。
例えば、Modelに記述すべき処理をControllerに記述してしまうとFat Controller
(コードが大量に書かれて膨れ上がったController)になるなどの問題が発生しやすくなる。

Controllerのコード量を減らす方法

Modelに記述する。

上記のMVCの各役割を考えて、データの処理・加工を担うメソッドはModelに記述する。

訂正前

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.order(created_at: :desc).limit(10)
  end
end

訂正後(Modelに移動)

Modelクラスに対して直接呼び出せるようクラスメソッドとして定義。

app/models/post.rb
class Post < ApplicationRecord
  def self.latest(number)
    order(created_at: :desc).limit(number)
  end
end

Controllerでメソッドを呼び出す

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.latest(10)
  end
end

クラスメソッドでなく、scopeを使うことも出来る。

app/models/post.rb
class Post < ApplicationRecord
  scope :latest, -> (number = 10){order(created_at: :desc).limit(number)}
end
app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.latest
  end
end

Modelのコード量を減らす方法

Concernを使う

複数のModelに同じ処理が繰り返し記述されている場合などに、Concernを使って共通処理を切り出すことが出来る。

app/models/post.rb
scope :latest, -> (number = 10){order(created_at: :desc).limit(number)}
def hoge
  puts "hogehoge"
end
app/models/comment.rb
scope :latest, -> (number = 10){order(created_at: :desc).limit(number)}
def hoge
  puts "hogehoge"
end

app/models/concernsにファイルを作成・共通処理を記述。

app/models/concerns/common_module.rb
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することで共通処理が使用できる。

app/models/post.rb
include CommonModule
app/models/comment.rb
include CommonModule

バリデーションを切り出す

長くなりがちなバリデーションの記述をvalidatorに切り出すことが出来る。
appディレクトリ下にvalidatorsディレクトリを作成し、バリデーション用のファイルを作成する。

app/validators/post_validator.rb
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側に追加で記述する。

app/models/post.rb
validates_with PostValidator

コールバックを切り出す

コールバックもModelから切り出すことが出来る。
app/callbacksディレクトリを作成し、コールバック用のファイルを作成する。
(クラス名はコールバック名と同じにすること)

app/callbacks/post_callback.rb
class PostCallback
  def before_create(post)
    post.title = "No Title" if post.title.blank?
  end
end

Model側に追加で記述する。

app/models/post.rb
before_create PostCallback.new
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