Как реализовать модель дружбы в 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 |
Ответы
Ответ 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 Майкла Хартла и Аврелия Прохазки. Здесь исходный код, который поможет вам улучшить ваше решение.
Ответ 2
Конечная ссылка:
http://railscasts.com/episodes/163-self-referential-association
Ответ 3
Короткий ответ - да. Просто создайте другую запись дружбы, чтобы представлять двунаправленную ассоциацию.
Я написал драгоценный камень под названием has_friendship для этой проблемы. Все, что вам нужно сделать, это падение has_friendship
в вашей модели, и все ассоциации и методы будут учтены.
Надеюсь, это поможет!
Ответ 4
Прочитайте этот учебник, иллюстрирующий модель отношений в Rails Tutorials. Это должно быть именно то, что вы ищете.
Ответ 5
Я рекомендую вам книгу RailsSpace: создание сайта социальной сети. В нем четко объясняется, как реализовать модель дружбы. Хотя это не распространяется на другие формы отношений, но довольно применимо к вашей проблеме.