Reputation: 13
I created 3 models, User, City, UserCity.
User class:
class User < ActiveRecord::Base
has_many :user_cities, :dependent => :destroy, :uniq => true
has_many :cities, :through => :user_cities
end
City class:
class City < ActiveRecord::Base
has_many :user_cities, :dependent => :destroy, :uniq => true
has_many :users, :through => :user_cities
end
UserCity class:
class UserCity < ActiveRecord::Base
belongs_to :user
belongs_to :city
end
And then I tried
u = User.new()
c = City.new()
u.cities << c
c.users << u
p UserCity.all.size # => 2
user_cities table had duplicates. So then, I coded
UserCity class:
class UserCity < ActiveRecord::Base
validates :user_id, :uniqueness => {:scope => :city_id}
belongs_to :user
belongs_to :city
end
and run the same ruby code above. But it failed after c.users << u
because I prohibited duplicate.
How can I make u.cities
have c
and c.users
have u
without duplicating data in join table?
Added:
So, if I choose only c.users << u
, can I only do this for cities
?
cities = Array.new()
UserCity.where(:user_id => u.id).each do |uc|
cities << City.find(uc.city_id)
end
Upvotes: 1
Views: 559
Reputation: 11196
You might also want to prevent duplicates in the db by adding an index in the db which would raise an error if you accidentally try to add a duplicate join entry. Do something like this in a migration:
add_index :cities_users, [:city_id, :user_id], unique: true
Upvotes: 0
Reputation: 3773
Choose either u.cities << c
or c.users << u
. Each of them cause a row inserted in to the join table.
Upvotes: 2