delegateを使って関連先データを簡潔に取得する
- 最終更新日: 2025年1月14日(火)
- 公開日: 2025年1月15日(水)

こんにちは。デザイン・システム室の永野です。
今回は、Rails の delegate を用いた関連先データの取得方法についてまとめてみました。
以前から存在自体は認識していたのですが、あまり使用したことがなかったので、試しに使用してみると、意外に便利なことに気づきました。
これからdelegateを用いて、関連先データを取得してみたいと考えている方の参考になれば幸いです。
delegate とは??
delegate は、関連するモデルやオブジェクトの属性やメソッドを簡潔に呼び出せるようにするためのヘルパーメソッドです。これにより、コードの可読性を向上させ、冗長な記述を減らすことができます。
使い方は下記の通りです。
# 対象のUserモデルのインスタンスにひもづくProfileモデルの nameカラムの値が、「テスト太郎」とする
> User.last.profile.name
=> "テスト太郎"
# user.rb
class User < ApplicationRecord
has_one :profile
def name
profile.name
end
end
# Userモデルに定義したnameメソッドを実行し、nameカラムの値を取得
> User.last.name
=> "テスト太郎"
# delegate を使用し、profiles テーブルのnameカラムの値を取得
class User < ApplicationRecord
has_one :profile
delegate :name, to: :profile
end
> User.last.name
=> "テスト太郎"
参考
Active Support コア拡張機能 – Railsガイド
delegateを用いた関連先データの取得
今回は、下記のようなモデルでリレーションが組まれていた時、customer_coupons テーブルから customer_coupons > serial_numbers > items > unifide_codes テーブルの code カラムの値を取得したいと考えていました。
class CustomerCoupon < ApplicationRecord
belongs_to :serial_number, optional: true
end
class SerialNumber < ApplicationRecord
has_one :customer_coupon
end
class Item < ApplicationRecord
belongs_to :unified_code, optional: true
has_many :serial_numbers
end
class UnifiedCode < ApplicationRecord
has_one :item, dependent: :destroy
end
そこで、当初は、下記のようなかたちでcode カラムの値を取得しようと考えていました。
# code カラムの値を取得
> CustomerCoupon.last.serial_number.item.unified_code.code
=> "2005181101"
ただ、これだと、customer_coupons テーブルにひもづくunified_codes テーブルの code カラムの値を取得したいとなった時、毎回このような記述をするのは少し冗長な気がしました。
また、customer_coupons テーブルにひもづくunified_codes テーブルの code カラムの値を取得するためだけに、CustomerCouponモデルに unified_codes テーブルの code カラムの値を取得するためのインスタンスメソッドを作成するのも、少し違う気がしました。
そこで、delegate を使用し、より簡単にcodeカラムの値を取得していきたいと思います。
実装した内容が下記の通りです。
class CustomerCoupon < ApplicationRecord
belongs_to :serial_number, optional: true
delegate :item, to: :serial_number
delegate :code, to: :item, prefix: true
end
class Item < ApplicationRecord
belongs_to :unified_code, optional: true
has_many :serial_numbers
delegate :code, to: :unified_code
end
まず、行なっていることは、CustomerCoupon モデルで、serial_number 経由で、itemを取得し、CustomerCoupon.last.serial_number.item で item を取得できるようにしています。
また、Itemモデルで、unified_code 経由で、code カラムの値を取得しています。
そして、CustomerCoupon モデルで、item 経由で、code カラムの値を取得しています。
また、prefix を用いることで、CustomerCoupon.last.item_code といったかたちで、customer_coupons テーブルから unified_codes テーブルの code カラムの値を直接取得することができます。
CustomerCoupon.last.item_code の実行結果が下記の通りです。
> CustomerCoupon.last.item_code
=> "2005181101"
上記より、delegate を用いて、customer_coupons テーブルから unified_codes テーブルの code カラムの値を取得することができることを確認できました。
まとめ
今回は、関連先のデータをdelegate を用いて取得する方法を紹介しました。
個人的には、とても便利な機能であると思いました。
また、delegate 自体メソッドとして扱われるので、render json: coupon.as_json(methods: [:serial, :item_code]) のように、JSON形式で実行結果をフロント側に返すことも可能らしいです。
今後も delegate を適切なかたちで使用していきたいです。
現在デザイン・システム室では、新しいメンバーを募集しています。
少しでも興味を持たれた方は、ぜひご応募ください。
皆様からのご応募、心よりお待ちしております。