Reputation: 11
I have a model Friendship where :friend_id is also a foreign key as :user_id
friendships id | user_id | friend_id I'm aware that validating the uniqueness of the two fields would be something like this
validates :user_id, :uniqueness => {:scope => :friend_id}
But is there a way to validate
user_id = 1, friend_id = 3
user_id = 3, friend_id = 1
so that only user_id = 1, friend_id = 3 is stored?
Upvotes: 0
Views: 1134
Reputation: 76774
Join Model
Looks like you're using a join model
with Rails - as mentioned in the comments, you'll want to change this to friendship
(not friend
).
Rails has two types of join
mechanism - has_many :through
and has_and_belongs_to_many
- both allow you to associate many-to-many
records, like this:
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :friendships
has_many :friends, through: :friendships
end
#app/models/friendship.rb
Class Friendship < ActiveRecord::Base
belongs_to :friend, class: "User", foreign_key: "friend_id"
belongs_to :user
end
#friendships
id | user_id | friend_id | created_at | updated_at
I would recommend you have a friendship
model (as opposed to a model-less HABTM
setup), because HMT
allows you to add extra data, such as created_at
, updated_at
, permissions
, etc)
Self Referential
I would also use a self-referential
model. This will allow you to keep a single model (for User
), and then call @user.friends
without an issue.
Whether my above association definitions are correct is another matter; this is how you'd want to set them up.
--
Validation
In terms of validating your associations, I believe you'll be able to use indexes in your DB. This is used often for HABTM
tables -
#Migration
# Adding the index can massively speed up join tables. Don't use the
# unique if you allow duplicates.
add_index(:friendships, [:user_id, :friend_id], :unique => true)
This will work for your original case, but not for the second
Upvotes: 1