我目前正在开发一个小型社交网络应用程序,现在我正在尝试创建一个代表用户之间友谊的模型。这是我到目前为止所提出的:
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
我的友谊模型有一个字段已确认为boolean我想使用 将友谊定义为待决或确认。
如何访问特定用户的所有待处理请求?我可以以某种方式定义 这使用Rails的范围方法?像
这样的东西current_user.friendships.requests # => [Friendship, Friendship, ...]
会很棒。
如何将此关联设为双向?我只是添加另一个 友谊一旦确认了朋友请求,以便我的友谊 表看起来与此类似:
| user_id | friend_id | confirmed |
-----------------------------------
| 1 | 2 | true |
| 2 | 1 | true |
答案 0 :(得分:30)
要访问所有待处理的友情,您可以使用关联:
has_many :pending_friends,
:through => :friendships,
:source => :friend,
:conditions => "confirmed = 0" # assuming 0 means 'pending'
要使友谊双向化,您可能希望将字符串 status 列替换为布尔已确认列,该列具有以下三个值之一:'pending', '已请求'和'已接受'(可选“已拒绝”)。这将有助于跟踪谁发出了友谊请求。
当发送友谊请求时(例如从Foo发送到Bar),您创建两个友谊记录(封装在事务中):一个请求,一个挂起以反映resp。 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
当友谊被接受时(例如通过Bar),两个友谊记录都被设置为接受。
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
这一点在迈克尔·哈特尔和Aurelius Prochazka的“铁路空间”一书的第14章中有所论述。这是source code,它可以帮助您优化解决方案。
答案 1 :(得分:12)
答案 2 :(得分:3)
简短的回答是肯定的。只需制作另一张友谊记录即可表示双向关联。
我为这类问题写了一个名为has_friendship的宝石。您需要做的只是在模型中放入has_friendship
,并且将处理所有关联和方法。
希望这有帮助!
答案 3 :(得分:2)
阅读关于Rails教程的this tutorial illustrating a relationship model。它应该是你正在寻找的。 p>
答案 4 :(得分:1)
我向您推荐RailsSpace:构建社交网站。它清楚地解释了如何实现友谊模型。虽然它不能扩展到其他形式的关系,但非常适合你的问题。