我目前正在开发一个小型社交网络应用程序,现在我正在尝试创建一个模型,代表用户之间的友谊。这是我目前想到的:
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 |
要访问所有未决的友谊,您可以使用关联:
has_many :pending_friends,
:through => :friendships,
:source => :friend,
:conditions => "confirmed = 0" # assuming 0 means 'pending'
要使友谊双向,您可能希望将布尔确认列替换为字符串状态列,该列具有以下三个值之一:'pending', 'requested'和'accepted'(可选'rejected')。这将有助于跟踪谁提出了友谊请求。
当一个友谊请求被发送时(比如从Foo到Bar),你创建了两个友谊记录(封装在一个事务中):一个请求,一个挂起,以反映响应。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
这在Michael Hartl和Aurelius Prochazka所著的Railspace一书的第14章中有很大的介绍。下面是源代码,可以帮助您改进解决方案。
最终参考:
http://railscasts.com/episodes/163-self-referential-association简短的回答是肯定的。再做一个友情记录来表示双向的联系。
对于这种问题,我写了一个叫做has_friendship的gem。你所需要做的就是在你的模型中加入has_friendship
,所有的关联和方法都将被处理。
希望这对你有帮助!
阅读本教程,说明Rails教程中的关系模型。
我向您推荐《RailsSpace:构建一个社交网站》这本书。它清楚地解释了如何实现一个友谊模型。虽然它不能扩展到其他形式的关系,但对于你的问题是非常适用的。