composed_ofでhas_manyぽくする

ActiveRecordなオブジェクトとPOROなオブジェクトを、1対多で関連付けたかった。

環境

方法

  1. POROでエンティティクラスを定義する
  2. POROでエンティティの集約クラスを定義する
  3. ActiveRecord継承クラスと集約クラスをcomposed_ofする

サンプル

class User
  attr_reader :id, :group_id, :name
  def initialize(id:, group_id:, name:)
    @id = id
    @group_id = group_id
    @name = name
  end
end

class Users
  # May need more.
  delegate :each, to: :users

  def initialize(group_id)
    @users = aggregate_users(group_id)
  end

  def user_ids
    users.map(&:id)
  end

  private

  attr_reader :users
  def aggregate_users(group_id)
    # It's a sample.
    (1..100).map {|i| User.new(id: i, group_id: group_id, name: i) }
  end
end

class Group < ApplicationRecord
  composed_of :users, class_name: "Users", mapping: [%w[id group_id]]
  delegate :user_ids, to: :users
end