2009-04-28 3 views
4

Mit ActiveRecord habe ich ein Objekt, Client, dass null oder mehr Benutzer (d. H. Über eine has_many-Zuordnung). Der Client verfügt auch über das Attribut 'primary_contact', das manuell festgelegt werden kann, aber immer auf einen der zugeordneten Benutzer verweisen muss. I.e. primary_contact kann nur leer sein, wenn keine Benutzer zugeordnet sind.Wie kann ich einen gültigen Verweis auf ein bestimmtes Objekt in einer ActiveRecord-Verknüpfung erstellen/verwalten?

Was ist der beste Weg, Kunden zu implementieren, so dass:

a) Das erste Mal, wenn ein Benutzer an einem Client hinzugefügt wird, primary_contact gesetzt auf diesen Benutzer zeigen?

b) Der primary_contact befindet sich immer in der Benutzerassoziation, es sei denn, alle Benutzer werden gelöscht? (Dies hat zwei Teile: wenn ein neuer primary_contact gesetzt oder ein Benutzer aus der Assoziation entfernt wird)

Mit anderen Worten, wie kann ich den Titel des "primären Kontakts" einem Benutzer eines bestimmten Kunden zuweisen und neu zuweisen? Ich habe mit zahlreichen Filtern und Validierungen herumgebastelt, aber ich kann es einfach nicht richtig machen. Jede Hilfe wäre willkommen.


UPDATE: Obwohl ich bin sicher, dass eine Vielzahl von Lösungen gibt es, landete ich User Client informieren, die, wenn sie und dann unter Verwendung eines BEFORE_SAVE Anruf-Client gelöscht wird zur Validierung (und Satz, falls erforderlich) sein primärer_kontakt. Dieser Aufruf wird vom Benutzer kurz vor dem Löschen ausgelöst. Dies erfasst nicht alle Kantenfälle beim Aktualisieren von Verknüpfungen, aber es ist gut genug für das, was ich brauche.

Antwort

1

Obwohl ich bin sicher, dass eine Vielzahl von Lösungen gibt es, landete ich User Client informieren, die, wenn sie gelöscht werden soll und dann einen Anruf BEFORE_SAVE in-Client zu bestätigen (und eingestellt, falls erforderlich) ihre primary_contact . Dieser Aufruf wird vom Benutzer kurz vor dem Löschen ausgelöst. Dies erfasst nicht alle Kantenfälle beim Aktualisieren von Verknüpfungen, aber es ist gut genug für das, was ich brauche.

1

Meine Lösung ist alles im Join-Modell zu tun. Ich denke, dass dies auf den Client-Übergängen zu oder von Null-Verknüpfungen korrekt funktioniert, wobei immer garantiert wird, dass ein primärer Kontakt bezeichnet wird, wenn es eine bestehende Verbindung gibt. Ich würde mich freuen, jemandes Feedback zu hören.


Ich bin neu hier, so kann ich unten François nicht kommentieren. Ich kann nur meinen eigenen Eintrag bearbeiten. Seine Lösung geht davon aus, dass Benutzer zu Kunde eins zu viele sind, während meine Lösung viele zu viele voraussetzt. Ich dachte, dass das Benutzermodell vielleicht einen "Agenten" oder "Repräsentanten" repräsentiert und sicher mehrere Clients verwalten würde. Die Frage ist in dieser Hinsicht mehrdeutig.


class User < ActiveRecord::Base 
    has_many :user_clients, :dependent => true 
    has_many :clients, :through => :user_client 

end 

class UserClient < ActiveRecord::Base 

    belongs_to :user 
    belongs_to :client 

    # user_client join table contains :primary column 

    after_create :init_primary 
    before_destroy :preserve_primary 

    def init_primary 
    # first association for a client is always primary 
    if self.client.user_clients.length == 1 
     self.primary = true 
     self.save 
    end 
    end 

    def preserve_primary 
    if self.primary 
     #unless this is the last association, make soemone else primary 
     unless self.client.user_clients.length == 1 
     # there's gotta be a more concise way... 
     if self.client.user_clients[0].equal? self 
      self.client.user_clients[1].primary = true 
     else 
      self.client.user_clients[0].primary = true 
     end 
     end 
    end 
    end 

end 

class Client < ActiveRecord::Base 
    has_many :user_clients, :dependent => true 
    has_many :users, :through => :user_client 

end 
0

ich tun würde, das auf Benutzer ein boolean-Attribut. #has_one kann verwendet werden, um das erste Modell zu finden, bei dem dieser boolesche Wert auf "true" gesetzt ist.

class Client < AR::B 
    has_many :users, :dependent => :destroy 
    has_one :primary_contact, :class_name => "User", 
          :conditions => {:primary_contact => true}, 
          :dependent => :destroy 
end 

class User < AR::B 
    belongs_to :client 

    after_save :ensure_only_primary 
    before_create :ensure_at_least_one_primary 
    after_destroy :select_another_primary 

    private 
    # We always want one primary contact, so find another one when I'm being 
    # deleted 
    def select_another_primary 
    return unless primary_contact? 
    u = self.client.users.first 
    u.update_attribute(:primary_contact, true) if u 
    end 

    def ensure_at_least_one_primary 
    return if self.client.users.count(:primary_contact).nonzero? 
    self.primary_contact = true 
    end 

    # We want only 1 primary contact, so if I am the primary contact, all other 
    # ones have to be secondary 
    def ensure_only_primary 
    return unless primary_contact? 
    self.client.users.update_all(["primary_contact = ?", false], ["id <> ?", self.id]) 
    end 
end 
Verwandte Themen