はじめに
既存の画像データを新しいテーブル構造に移行する際、あまり変更を加えずにメソッドを扱えるようにデータの整合性を保ちつつ効率的に移行する方法を考えました。CarrierWaveを使用した画像の管理を例に、中間テーブルを介して画像データを別テーブルに移行する際のオーバーライドについて説明します。
背景
既存の Product モデルに直接関連付けられていた画像データを、新しい ProductImage モデルに移行することを例にし、画像の参照は中間テーブル ProductImageReference を介して行われるとして進めていきます。
実装ステップ
ImageUploader というCarrierWaveのアップローダーを ProductImage モデルにマウントされている状態にします。
class ProductImage < ApplicationRecord
mount_uploader :image, ImageUploader
# その他の設定
end
- オーバーライドの実装
Product モデル内で、画像データの参照方法を以下のようにオーバーライドしてみます
def image
product_image&.image || super
end
上記のようにすると product_image は新しい画像モデルのインスタンスを参照し、存在する場合はその image を、そうでない場合は既存のメソッドを呼び出します。
結果
この方法により、新しい ProductImage モデルを用いて画像データを管理しつつ、既存の画像パスは保持されます。新しくアップロードされる画像は、カスタマイズされたパスに保存されます。
上記を使う場合は移行するタイミングが必要です。
まとめ
本記事では、CarrierWaveを使用した画像データのオーバーライドと新旧のデータ構造の共存方法について考えました。
追記 ※単一責任の原則について
単一責任の原則(Single Responsibility Principle, SRP)は、ソフトウェア設計の原則の一つで、「クラスは一つの理由だけで変更されるべきである」とされます。
この原則は、クラスやメソッドが一つの機能や責任だけを持つべきだという考えです。
オーバーライドされた image メソッドの問題点
オーバーライドされた image メソッドは、二つの異なるソース(新しい ProductImage モデルと既存の画像)からデータを取得するという二つの責任を持っています。
このような場合、下記のような問題が想定されます。
- 保守性の低下:
メソッドが複数の責任を持つことで、そのメソッドのロジックが複雑になります。この場合では二つの異なるソースに対する変更を同時に考慮する必要が出てきます。 - 拡張性の問題
- 可読性の低下
(詳しく書くと長くなるので補ってください)