LoginSignup
2
1

More than 3 years have passed since last update.

Railsのポリモーフィック関連付けのテストを考えてみた。

Last updated at Posted at 2020-12-05

なぜ今回の記事を書いたか。

Railsの場合、ポリモーフィック関連付けを行なった際に紐づくモデルに対して実装しなければいけないメソッドの強制が行われません。そのため、メソッドの定義を忘れた場合エラーが発生します。
ただ、実装する際に忘れるメソッドのテストを書くのは難しいのでは? と個人的に思いました。
そのため、良し悪しは別として僕が実装したテストを記載します。

他に良い方法があれば是非教えてください!

実装したモデル

今回の記述に関係ない箇所に関しては省略しています。

app/models/notification.rb
class Notification < ApplicationRecord
  belongs_to :event, polymorphic: true
  
  
  
end
app/models/comment.rb
class Comment < ApplicationRecord
  has_many :notifications, as: :event, dependent: :destroy
  
  
  
  def notification_message()
    "#{self.user.name}によりコメントされました。"
  end
end

実装したテスト

ポリモーフィック関連付けに紐づくテストなので、Notificationのモデルテストに記載いたしました。

spec/models/notification_spec.rb
require 'rails_helper'

RSpec.describe Notification, type: :model do
  it 'Notificationと関連づいているクラスに対して必要なメソッドが定義されているか' do
    # 定数オブジェクトの一覧を取得。
    constants = Object.constants.map do |name|
      Object.const_get(name)
    end
    # Notificationモデルと紐づいているモデルを取得する
    models = constants.select do |c|
      # モデルクラスを絞り込む
      next unless c.class == Class && c < ActiveRecord::Base && !c.abstract_class? 
      # Notificationモデルが紐づいているか絞り込む
      c.reflect_on_all_associations.map(&:name).include?(:notifications)
    end
    models.each do |model|
      # 定義されたメソッドがあるかを確認する
      expect(model.method_defined?(:notification_message)).to be true
    end
  end
end

この実装を行う事で、自動的にポリモーフィック関連付けされたモデルに必要なメソッドが存在しているかを確認してくれる。これでポリモーフィック関連付けを行なった際にメソッド忘れは無くなります!

懸念点

  • モデルの数が多くなった時にテスト時間が増えそう
  • モデルテストで、他のモデルにメソッドがあるか確認するのは良いのか?
  • テストでここまで処理を書くのは良いのか?
  • ポリモーフィック関連付けで関連づいたモデルに対してメソッドの強制を行う方法が他にあるのではないか?
  • 継承やmoduleを使用した方が良いのではないか?

参考にしたサイト

2
1
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
2
1