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

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

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 ' scope ?Было бы замечательно что-то вроде

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

.

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

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

Ответы [ 5 ]

30 голосов
/ 10 апреля 2011

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

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 книги "Железнодорожное пространство" Майкла Хартла и Аврелия Прохазки. Вот исходный код , который должен помочь вам усовершенствовать ваше решение.

12 голосов
/ 10 апреля 2011
3 голосов
/ 02 декабря 2014

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

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

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

2 голосов
/ 10 апреля 2011

Прочтите это руководство, иллюстрирующее модель отношений в Rails Tutorials. Это должно быть именно то, что вы ищете.

1 голос
/ 08 января 2013

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

...