2006-05-11

_ [rails] has_many :through

class Group < ActiveRecord::Base
  has_many :assigns
  has_many :members, :through => :assigns
end

class Member < ActiveRecord::Base
  has_many :assigns
  has_many :groups, :through => :assigns
end

class Assign < ActiveRecord::Base
  belongs_to :group
  belongs_to :member
end

if __FILE__ == $0
  [Group, Member, Assign].each(&:delete_all)
  (1..5).each do |i|
    Group.create(:name => "group#{i}")
    Member.create(:name => "member#{i}")
  end
  (1..5).each do |i|
    (1..5).each do |j|
      Assign.create(:group_id => i, :member_id => j,
        :leader => rand(3).zero?) if rand(2).zero?
    end
  end

  # リーダー連中の名前
  p Member.find(:all, :include => :assigns).inject([]){|leaders, member|
    returning(leaders){leaders << member.name if member.assigns.any?(&:leader?)}}

  # 冗長版 
  p Member.find(:all, :include => :assigns).inject([]){|members, member|
    members << [member, member.assigns]
  }.select{|member, assigns|
    assigns.any?(&:leader?)
  }.map(&:first).map(&:name)
        ^^^^^^^ ktkr

  # リーダーがいないグループの名前
  p Group.find(:all, :include => :assigns).reject{|group|
    group.assigns.any?(&:leader?)}.map(&:name)

  # メンバーがいないグループの名前
  p Group.find(:all, :include => {:assigns => :member}).select{|group|
    group.members.empty?}.map(&:name)

  # 多分上のと同じ意味で、ちょっと効率がヨサゲ版
  p Group.find(:all, :include => :assigns).select{|group|
    group.assigns.empty?}.map(&:name)

  # メンバー→グループの割り当て表(リーダー属性つき)
  p Member.find(:all, :include => {:assigns => :group}).inject({}){|members, member|
    returning(members) do
      members.store(member.name, member.assigns.map{|assign|
          [assign.group.name, assign.leader?]})
    end
  }
end

確かに中間テーブルがモデルとして使えるのはいいですね。 ただ、問題は更新なんすよね。また今度。

本日のTrackBacks(全1件) []
_ Nov's daily? report:has_many :through (2) (2006-05-12 12:33)

まさしく has_many :through なサイトを見て、 昨日のに追記。:uniq とは関係ないけど。 class Group &lt; ActiveRecord::Base has_many :assigns has_many :members, :through =&gt; :assigns has_many :leaders, :through =&gt; :assigns, :source =&gt; :leader, :conditions..