Подтвердить что ты не робот

Как реализовать модель дружбы в Rails 3 для приложения для социальных сетей?

В настоящее время я работаю над небольшим социальным сетевым приложением, и сейчас я пытаюсь создать модель, которая представляет дружбу между пользователями. Это то, к чему я придумал:

class User < ActiveRecord::Base

  # ...
  has_many :friendships
  has_many :friends, :through => :friendships

end

class Friendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, :class_name => 'User'
end

Моя модель дружбы имеет поле, подтвержденное как логическое, которое я бы хотел использовать определить дружбу как ожидающую или подтвержденную.

Как я могу получить доступ ко всему ожидающему запросу для определенного пользователя? Могу ли я как-то определить это использование метода областей Rails? Что-то вроде

current_user.friendships.requests # => [Friendship, Friendship, ...]

было бы здорово.

Как я могу сделать эту ассоциацию двунаправленной? Я просто добавляю еще один дружба, как только кто-то подтвердил просьбу друга, чтобы моя дружба таблица будет выглядеть примерно так:

| user_id | friend_id | confirmed |
-----------------------------------
| 1       | 2         | true      |
| 2       | 1         | true      |
4b9b3361

Ответ 1

Чтобы получить доступ к ожидающим дружеским отношениям, вы можете использовать ассоциацию:

has_many :pending_friends,
         :through => :friendships,
         :source => :friend,
         :conditions => "confirmed = 0"  # assuming 0 means 'pending'

Чтобы сделать дружбу двунаправленной, вы можете заменить свой логический подтвержденный столбец столбцом состояния строки, который имеет одно из следующих трех значений: "ожидающий", "запрошенный" и "принятый" (опционально "отклоненный" ). Это поможет отслеживать, кто сделал запрос дружбы.

Когда отправляется запрос дружбы (скажем, от Foo до Bar), вы создаете две записи дружбы (заключенные в транзакцию): один запрошенный и один, ожидающий отражения соответственно. что у Бар есть запрошенная дружба от Foo и 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 книги Railspace Майкла Хартла и Аврелия Прохазки. Здесь исходный код, который поможет вам улучшить ваше решение.

Ответ 3

Короткий ответ - да. Просто создайте другую запись дружбы, чтобы представлять двунаправленную ассоциацию.

Я написал драгоценный камень под названием has_friendship для этой проблемы. Все, что вам нужно сделать, это падение has_friendship в вашей модели, и все ассоциации и методы будут учтены.

Надеюсь, это поможет!

Ответ 5

Я рекомендую вам книгу RailsSpace: создание сайта социальной сети. В нем четко объясняется, как реализовать модель дружбы. Хотя это не распространяется на другие формы отношений, но довольно применимо к вашей проблеме.