Для доступа ко всем ожидающим дружеским отношениям вы можете использовать ассоциацию:
has_many :pending_friends,
:through => :friendships,
:source => :friend,
:conditions => "confirmed = 0" # assuming 0 means 'pending'
Чтобы сделать дружбу двунаправленной, вы можете заменить логический подтвержденный столбец строкой status столбец, который имеет одно из следующих трех значений: 'pending', 'запрашивается 'и' принято '(опционально' отклонено '). Это поможет отследить, кто сделал запрос на дружбу.
Когда отправляется запрос о дружбе (скажем, из Foo в Bar), вы создаете две записи о дружбе (заключенные в транзакцию): одну запрошенную и одну ожидающую отражения, соответственно. у этого Бара есть запрошенная дружба с Фу, а у Фу - дружба с Баром.
def self.request(user, friend)
unless user == friend or Friendship.exists?(user, friend)
transaction do
create(:user => user, :friend => friend, :status => 'pending')
create(:user => friend, :friend => user, :status => 'requested')
end
end
end
Когда дружба принята (например, Бар), обе записи дружбы устанавливаются как принятые.
def self.accept(user, friend)
transaction do
accepted_at = Time.now
accept_one_side(user, friend, accepted_at)
accept_one_side(friend, user, accepted_at)
end
end
def self.accept_one_side(user, friend, accepted_at)
request = find_by_user_id_and_friend_id(user, friend)
request.status = 'accepted'
request.accepted_at = accepted_at
request.save!
end
Это в значительной степени освещено в главе 14 книги "Железнодорожное пространство" Майкла Хартла и Аврелия Прохазки. Вот исходный код , который должен помочь вам усовершенствовать ваше решение.