Gestión de las relaciones del niño con una representación de atributo anidado
-
11-09-2019 - |
Pregunta
Lo que estoy tratando de hacer es la siguiente:
En cualquier momento el usuario puede tener 1 perfil activo. Este perfil activo debe ser autorizado por un administrador para asegurarse de que cumple con las normas y reglamentos del sitio. Cuando un usuario edita su perfil su perfil público no se ve afectada hasta que el administrador se despide sus cambios. Si hacen una edición mientras que su perfil está en revisión, sus ediciones se aplican al perfil sobresaliente para su revisión y se inserta en la parte posterior de la cola.
Mis modelos tienen el siguiente aspecto:
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
Hay un pequeño giro ... el usuario no debe ser capaz de modificar el perfil directamente, como la colección de perfiles no está expuesto. En su lugar, editar su usuario y los campos de perfil se muestran allí.
¿Cuál es la mejor manera de manejar esto? Actualmente estoy usando:
accepts_nested_attributes_for :profiles
En el usuario, pero que parece bastante hacky. Lo ideal sería que la mayor parte de esta lógica vivirían en el modelo, pero la otra cosa que estoy coqueteando con es el uso de un presentador.
Cualquier idea sería muy apreciada, que me haga saber si necesita más información como un comentario y voy a actualizar este post adecuadamente.
Solución
Tal vez debería intentar tener dos relaciones de usuario perfil. Una de ellas es la que ellos pueden editar a través de su interfaz de usuario, y el otro es el que es aprobado por el administrador.
Se podría trabajar algo como:
class User < AB:B
has_one :profile #the user-editable one one
has_one :active_profile, :class_name=>"profile" #the one shown
end
Cada cambios en el perfil del usuario a través del formulario a continuación se muestran para el administrador (usando y observador o tal vez sólo y "after_save" filtro). Cuando se APRUEBA ella, los cambios se vierten a la active_profile uno, y se muestran en alguna parte.
De esta manera, se puede tener una interfaz de forma limpia y siempre que editar de nuevo, lo consideran el último perfil (pero no aprobado). También puede ordenar la cola utilizando la columna updated_at para ganar los "sus ediciones se aplican al perfil sobresaliente para su revisión y se inserta en la parte posterior de la cola" funcionalidad.
Otros consejos
Me ir sobre esto haciendo que el modelo de usuario tiene una relación con dos perfiles como se sugirió anteriormente también. Una "Aprobado" el perfil, y el otro para la edición que entra en su cola de administración.
Sin embargo, con el fin de manejar las transiciones entre los "pendientes" y "perfiles aprobados" perfiles Yo sugeriría posiblemente la adición de una máquina de estados para manejar las transiciones. La gema AASM ha sido bueno para mí en un proyecto reciente. ( http://github.com/rubyist/aasm/tree/master ), y creo que Edge Rails tiene derecho justo al horno de Estado en Machinage también. ( http://github.com/rails/rails/commit/aad5a30bf25d8a3167afd685fc91c99f4f09cc57 )
Su modelo podría ser algo como esto:
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
A continuación, podría llamar el perfil User.update pendientes! o perfil User.update aprobado! para la transición entre los estados perfil y utilizar las devoluciones de llamada de transición para manejar el envío de los datos de edición entre el perfil y el perfil activo en espera.
Por lo que mediante el nested_attributes_for con su forma actual, no creo que es un truco, que he usado también para actualizar atributos anidados y trabajaría bien. En este caso, sin embargo puede que no necesite demasiado ya que tiene 2 perfiles (uno público, uno pendiente).
Es sólo una idea! Pensando en voz alta aquí!