2009-08-06 2 views
1

Was ich versuche, Folgendes zu tun ist:Verwalten Kind-Beziehungen mit einem verschachtelten Attribute bilden

Zu jeder Zeit ein Benutzer ein aktives Profil hat. Dieses aktive Profil muss von einem Administrator autorisiert werden, um sicherzustellen, dass es den Regeln und Vorschriften der Site entspricht. Wenn ein Benutzer sein Profil bearbeitet, bleibt sein öffentliches Profil erhalten, bis der Administrator die Änderungen abbildet. Wenn sie eine Bearbeitung vornehmen, während ihr Profil überprüft wird, werden ihre Änderungen auf das ausstehende Profil zur Überprüfung angewendet und an die Rückseite der Warteschlange verschoben.

Meine Modelle in etwa so aussehen:

class Profile < AR:B 
    belongs_to :user 
end 

class User < AR:B 
    has_many :profiles do 
     def active 
      ... 
     end 
     def latest 
     end 
    end 
    def profile 
     self.profiles.active 
    end 
end 

Es gibt einen kleinen Twist ... soll der Benutzer das Profil bearbeiten direkt nicht in der Lage sein, da die Sammlung Profile nicht ausgesetzt ist. Stattdessen bearbeiten sie ihren Benutzer und die Profilfelder werden dort angezeigt.

Was ist der beste Weg, dies zu verwalten? Zur Zeit verwende ich:

accepts_nested_attributes_for :profiles 

In den Benutzer, aber das scheint ziemlich hacky. Im Idealfall würde das meiste dieser Logik im Modell leben, aber die andere Sache, mit der ich flirte, ist die Verwendung eines Moderators.

Alle Gedanken würden sehr geschätzt, lassen Sie mich wissen, wenn Sie weitere Informationen als Kommentar benötigen, und ich werde diesen Beitrag entsprechend aktualisieren.

Antwort

2

Vielleicht sollten Sie versuchen, zwei Beziehungen von Benutzer zu Profil zu haben. Eine ist diejenige, die sie über Ihre Benutzerschnittstelle bearbeiten können, und die andere ist diejenige, die vom Administrator genehmigt wurde.

Es könnte so etwas wie arbeiten:

class User < AB:B 

has_one :profile #the user-editable one one 
has_one :active_profile, :class_name=>"profile" #the one shown 

end 

Jede Änderungen am Benutzerprofil über das Formular dann für den Admin zeigen würde (mit und Beobachter oder vielleicht auch nur und „after_save“ Filter). Wenn es angenommen wird, werden die Änderungen dann in active_profile 1 ausgegeben und irgendwo angezeigt.

Auf diese Weise können Sie eine saubere Formularschnittstelle haben, und wenn sie es erneut bearbeiten, sehen sie das neueste (aber nicht genehmigte) Profil. Sie können die Warteschlange auch mithilfe der Spalte "updated_at" anordnen, um zu erfahren, "dass die Bearbeitungen auf das herausragende Profil zur Überprüfung angewendet und an die Funktionalität der Warteschlange übertragen werden".

+0

Ursprünglich dachte ich daran, es so zu machen, aber ich habe es abgelehnt, weil ich dachte, dass es nicht ideal wäre, aber deine Aufschrift hat mich davon überzeugt, dass es der richtige Weg ist und werde wahrscheinlich meine Meinung und die Logik in das Modell ist einfacher. – jonnii

+0

Ich hätte wahrscheinlich erwähnen müssen, dass in diesem Fall die FK auf dem Benutzermodell sein muss, um zwischen den beiden Profilen zu unterscheiden, so dass es ein gehört, kein has_one. – jonnii

+0

Ja, Sie haben Recht. Obwohl ein bisschen wackelig auf die Semantik, BD-bezogen, das wäre richtig. – Yaraher

1

Ich würde gehen, indem der Benutzer Model eine Beziehung mit zwei Profilen haben, wie oben auch vorgeschlagen. Ein "Genehmigtes" Profil und das für die Bearbeitung, das in Ihre Admin-Warteschlange geht.

Um jedoch Übergänge zwischen "ausstehenden" Profilen und "genehmigten" Profilen zu behandeln, würde ich vorschlagen, möglicherweise eine Zustandsmaschine hinzuzufügen, um die Übergänge zu behandeln. Das AASM-Juwel hat mir in einem kürzlichen Projekt gut getan. (http://github.com/rubyist/aasm/tree/master), und ich glaube, Edge Rails hat eben auch State Machinage gebacken. (http://github.com/rails/rails/commit/aad5a30bf25d8a3167afd685fc91c99f4f09cc57)

Ihr Modell wie folgen aussehen könnte:

class User < AR:B 

has_one :active_profile 
has_one :pending_profile 

include ActiveRecord:: StateMachine 

state_machine do 
    state :approved 
    state :pending 
    state :rejected 

    event :update_profile_pending do 
    transitions :to => :pending, :from => [:approved], :on_transition => :send_to_admin_queue 
    end 

    event :update_profile_approved do 
    transitions :to => :approved, :from => [:pending], :on_transition => :update_current_profile 
    end 

    event :update_to_rejected do 
    transitions :to => :rejected, :from => [:pending] 
    end 
end 

def send_to_admin_queue 
    //method to handlesending pending profiles to admin for approval 
end 

def update_current_profile 
//method to handle updated profiles with changes 
end 

end 

Sie könnten dann anhängige User.update Profil aufrufe! oder User.update Profil genehmigt! Wechseln Sie zwischen Ihren Profilstatus und verwenden Sie die Übergangsrückrufe, um die Bearbeitungsdaten zwischen Ihrem aktiven Profil und dem ausstehenden Profil zu senden.

Soweit ich die nested_attributes_for mit Ihrem tatsächlichen Formular verwende, glaube ich nicht, dass es ein Hack ist, ich habe es auch verwendet, um verschachtelte Attribute zu aktualisieren, und es würde gut funktionieren. In diesem Fall brauchen Sie vielleicht auch nicht, da Sie 2 Profile haben (ein öffentliches, ein anhängiges).

Nur eine Idee! Hier laut nachdenken!

+0

Danke für die Antwort. Ich habe gesehen, dass die Staatsmaschine randvoll gerollt wurde ... Ich freue mich wirklich auf Rails 3.0! – jonnii