2011-12-20 57 views
5

Tàu giả với .push trên một hàng rào, đặt mối quan hệ habtm theo cả hai hướng. Mặc dù xóa sẽ xóa một bản ghi được liên kết nhưng không có cách nào được ghi lại để chỉ xóa mối quan hệ mà tôi đã thấy. Có cách nào tốt hơn để làm điều này?Theo dõi/theo dõi của HABTM theo dõi/theo dõi

Có cách nào tốt hơn để đảm bảo tính duy nhất không?

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 

Trả lời

18

mã sau làm việc tốt cho tôi (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 

Không inverse_class_name, không tiết kiệm cuộc gọi, không có xử lý đặc biệt, nhưng với loại trừ tự sau đây.

Lý do là, mongoid tự động sử dụng dependent: nullify nếu không được thêm vào câu lệnh quan hệ. Và với autosave: true cập nhật các mối quan hệ được lưu lại (và chỉ cần thiết cho việc theo dõi, bởi vì chúng tôi không thay đổi người theo dõi trực tiếp). Nếu không có tùy chọn tự động lưu, bạn cần phải thêm một cuộc gọi lưu trong các phương thức, vì mongoid không tự động lưu các cập nhật quan hệ (kể từ 2.0.0.x).

Tôi đặt mệnh đề if làm khối, vì vậy bạn có thể thay đổi nó bằng xử lý ngoại lệ (else raise FooException).

.delete(user) là không sao, cũng được đề cập trong tài liệu mongoid: http://mongoid.org/docs/relations/referenced/n-n.html (cuộn xuống phần "PHÂN PHỐI PHỤ HUYNH").

+0

Một số nội dung tuyệt vời tại đây. Tuy nhiên, tôi đã làm một số thử nghiệm trước đó, và rơi vào cùng một cái bẫy (trừ khi tôi nhầm): .delete (người dùng) xóa người dùng khỏi cơ sở dữ liệu và vô hiệu hóa tham chiếu đến bất kỳ tham chiếu nào được thực hiện cho người dùng đã bị xóa –

+0

.delete nằm trên băm .following không có trên chính đối tượng người dùng. Giống như doc nói "Orphan một mối quan hệ con duy nhất". Nó thực hiện công việc, tôi đã thử nghiệm nó và nó hoạt động. – asaaki

+0

Mã '! Self.following.include? (Người dùng)' rất tuyệt khi bạn không có quá nhiều người dùng bên trong mối quan hệ sau đây, nhưng nếu bạn có 10K người dùng… Hiệu suất không tuyệt vời:/ –

Các vấn đề liên quan