2011-12-20 98 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