2011-12-20 46 views
5

Mongoid随身携带.push,在两个方向上建立了一种双方的关系。尽管删除将删除关联的记录,但没有文档记载的方法来删除我已经看到的关系。有没有更好的方法来做到这一点?HABTM mongoid关注/追随者

确保唯一性有更好的方法吗?

has_and_belongs_to_many :following, {class_name: 'User', inverse_of: :followers, inverse_class_name: 'User'} 
    has_and_belongs_to_many :followers, {class_name: 'User', inverse_of: :following, inverse_class_name: 'User'} 

    def follow!(user) 
    self.following.push(user) # this pushes the inverse as well 
    self.following_ids.uniq! 
    self.save! 
    user.follower_ids.uniq! 
    user.save! 
    end 

    def unfollow!(user) 
    self.following.delete(user.id) 
    self.save! 
    user.followers.delete(self.id) 
    user.save! 
    end 

回答

18

下面的代码工作对我罚款(mongoid 2.3.x版本):

class User 
    include Mongoid::Document 

    field :name, type: String 

    has_and_belongs_to_many :following, class_name: 'User', inverse_of: :followers, autosave: true 
    has_and_belongs_to_many :followers, class_name: 'User', inverse_of: :following 

    def follow!(user) 
    if self.id != user.id && !self.following.include?(user) 
     self.following << user 
    end 
    end 

    def unfollow!(user) 
    self.following.delete(user) 
    end 
end 

没有inverse_class_name,没有节省话费,无需特殊处理,但自以下的排斥。

原因是,如果未添加到关系语句中,mongoid会自动使用dependent: nullify。并且autosave: true关系的更新得到保存(并且仅仅用于跟随,因为我们不直接改变关注者)。没有自动保存选项,您需要在方法中添加保存调用,因为mongoid不会自动保存关系更新(自2.0.0.x起)。

我把if子句作为块,所以你可以通过异常处理来改变它(else raise FooException)。

.delete(user)还行,在mongoid文档中也有提到:http://mongoid.org/docs/relations/referenced/n-n.html(向下滚动到“依赖行为”)。

+0

这里有一些很棒的东西。但是,我之前做了一些测试,并陷入了同样的陷阱(除非我错了):.delete(user)从数据库中删除用户,而nullify指的是对现在删除的用户的任何引用。 – 2011-12-21 23:15:09

+0

The .delete不在用户对象本身上。像医生说的“孤儿独子关系”。它完成了这项工作,我测试了它并发挥作用。 – asaaki 2011-12-22 02:44:32

+0

当您在以下关系中没有太多用户时,代码'!self.following.include?(user)'很酷,但是如果您拥有10K用户......性能不是很好:/ – 2012-01-05 17:45:24