2011-12-20 19 views
5

Mongoid wysyła z .push na habtm, który ustanawia związek habtm w obu kierunkach. Chociaż usuń # usunie powiązany rekord, nie ma udokumentowanego sposobu usunięcia tylko relacji, którą widziałem. Czy jest lepszy sposób na zrobienie tego?HABTM mongoid follow/follower

Czy istnieje lepszy sposób na zapewnienie wyjątkowości?

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 

Odpowiedz

18

następujący kod pracował dobrze dla mnie (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 

Nie inverse_class_name, bez oszczędzania połączeń, bez specjalnego trybu postępowania, ale z wykluczeniem z samojezdne następujący.

Powód jest taki, że mongoid automatycznie używa dependent: nullify, jeśli nie zostanie dodany do instrukcji relacji. I z autosave: true aktualizacja relacji zostaje zapisana (i jest potrzebna tylko do podążania, ponieważ nie zmieniamy bezpośrednio obserwujących). Bez opcji autozapisu musisz dodać metodę zapisu, ponieważ mongoid nie zapisuje automatycznie aktualizacji relacji (od 2.0.0.x).

Umieszczam klauzulę if jako blok, aby można było zmienić ją za pomocą obsługi wyjątków (else raise FooException).

The .delete(user) jest w porządku, również wspomniano w mongoidalnych dokumentach: http://mongoid.org/docs/relations/referenced/n-n.html (przewiń w dół do "ZACHOWANIA ZALEŻNOŚCI").

+0

Kilka świetnych rzeczy tutaj. Jednak wcześniej przeprowadziłem testy i wpadłem w tę samą pułapkę (chyba że się mylę): .delete (użytkownik) usuwa użytkownika z bazy danych, a unieważnienie odnosi się do wszelkich odniesień do usuniętego użytkownika. –

+0

.delete jest na mieszanie .fh, nie na samym obiekcie użytkownika. Tak jak doktor mówi: "Sierota to relacja jednego dziecka". Wykonuje to zadanie, testowałem i działa. – asaaki

+0

Kod '! Self.following.include? (User)' jest fajny, gdy nie masz zbyt wielu użytkowników w poniższym związku, ale jeśli masz 10 000 użytkowników ... Wydajność nie jest zbyt duża:/ –