ActiveRecordのhas_manyに:uniqを指定して重複を削除

ActiveRecordのhas_manyに:uniqを指定したときの動作を確認してみた。
グループの下に複数のユーザーがぶら下がっているテーブル構成を考える。

class Group < ActiveRecord::Base
  has_many :users, :uniq => true
end

class User < ActiveRecord::Base
  belongs_to :group
end

とか

class Group < ActiveRecord::Base
  has_many :users, :though => :groups_users, :uniq => true
  has_many :groups_users, :dependent => :destroy
end

class User < ActiveRecord::Base
  has_many :groups, :though => :groups_users, :uniq => true
  has_many :groups_users, :dependent => :destroy
end

という感じ。

consoleで

  • グループを作る g
  • ユーザーを作る u
  • 同じユーザーを何度も関連づける g.users << u
  • 重複して登録されているか確認する g.users.size

としてみる。

g = Group.create!
u = User.create!

10.times do 
 g.users << u
 p g.users.size
end

結果は

1
1
1
1
1
1
1
1
1
1

ということで重複なし。
:uniq => trueを付けない場合の挙動は以下。

1
2
3
4
5
6
7
8
9
10

という感じで重複して追加されていきます。

※ 中間テーブルを作らない1対多の構成( has_many :users と belongs_to :group の方)だと、そもそもテーブル構成的に:uniq=>trueなので、DB上は重複がない。