Creación de objeto complejo a través de varios controladores

Hola a todos de nuevo. Aviso que este correo es un poco largo y
complicado.

Se trata de la construcción de un objeto en varios pasos. Más
exactamente,
de construir un objeto A y su relacionado B. Se puede hacer por
separado,
pero mi intención es hacer el proceso lo más ágil posible y por eso está
planteado como un ‘wizard’.

El proceso comenzaría pidiendo los datos de B para, a continuación
seguir
con los de A. La dificultad surgió del hecho de que debía arrastrar el
objeto B creado al formulario de A. Una opción era guardarlo en BD y
seguir,
pasando el id del nuevo B, pero me dió problemas (que ya os comentaré
más
abajo) y opté por arrastrar los datos en la request.

Surgen ahora las siguientes cuestiones:

  • A y B tienen sus propios controladores
  • Cada controlador tiene sus propias reglas de validación. Lo suyo sería
    aprovecharlas para hacerlo ‘DRY’.
  • ‘render’ reutiliza la request, pero ‘redirect_to’ no, sin embargo
    ‘render’
    no se como hacer que procese un rhtml de otro controlador.

Os explico los pasos que intento seguir:

1 - Formulario de B. Rellenar y enviar al controlador de B, para usar la
validación de este.
2 - Del controlador de B intenta ir al formulario de A, pasandole el
params[:B] correspondiente.
3 - Formulario de A incluyendo la información de B. Rellenar y enviar al
controlador de A.

Los problemas están en el paso 2: ‘redirect_to’ permite usar otro
controlador ‘render’ no (que yo sepa). No se como hacer para desde un
controlador llamar a la validación de otro, por ello uso los
controladores
de A y B por separado, en lugar de incluir la creación de B en el
controlador de A. Lo malo es que si quiero pasar de uno a otro tengo que
hacerlo con ‘redirect_to’, que no conserva la request (y por tanto
pierdo el
params[:B])

Más esquemático:

Form B -->

controlador B
    @B = B.new(params[:B]
    ¿render? <---- debería llevarme al Form A ¿¿¿como???
end

Form A (debería recibir @B y volcarlo en el formulario A con campos

hidden) -->
controlador A
@B=B.new(params[:B])
@A=A.new(params[:A])
@B.save
@[email protected]

end

Probablemente haya una solución simple. Lo que a mi se me ha ocurrido es
hacerlo a base de partials, que parece que son independientes del
controlador. Desde estos partials puedo construir urls que me lleven al
controlador que quiero.

Form B -->

controlador B
    @B = B.new(params[:B]
    render Form A de este controlador? <---- debería llevarme al 

Form A
¿¿¿como???
end

views/B/Form A
    <-- :partial en views/A/_A que apunta al controlador A

controlador A
    ...
end

Sacar el proceso en partials me permite tambien construir directamente
un A
pasandole el id de un B ya existente.

Por último, otro problema que tuve fue que cuando hacía

Form B -> B.new -> B.save -> Form A ../A/new/<b_id>

en el navegador aparecía la url de Form A, pero si le daba a F5 y
recargaba
se ejecutaba de nuevo el B.save

B.new -> B.save -> Form A ../A/new/<b_id+1>

por ello me decidí a hacerlo arrastrando los datos en el params.

Esto es todo. Siento haber sido tan extenso, pero era necesario para
explicar bien el problema. Espero que os haya quedado suficientemente
claro.

un saludo y gracias
Rafa

(admito que me salte el 80% del texto asi que es posible que este
hablando cosas sin sentido)

Porque no usas metodos y modulos?

module Validaciones
def validar_a; …; end
def validar_b; …; end
end

class ControladorA
include Validaciones
def accion_a; …; validar_a; validar_b;… end
end

class ControladorB
include Validaciones
def accion_b; …; validar_b;… end
end

Espera, espera, espera, que acabo de ver una cosa…

Las validaciones NO se ponen en el controlador, sino en el MODELO

class A < ActiveRecord::Base
validates_presence_of :nombre

end

entonces sí que podría centralizar el proceso en el controlador de A, ya
que
el mero hecho de hacer B.new(params[:B]) debería disparar las
validaciones.

Voy a ponerme a ello…

Gracias de todas formas. Menos mal que te saltaste el 80% ;)))

Y aun así, si lo hubiera hecho con módulos ¿tendría que hacerme una
validación propia?

module Validaciones
def validaA
if(A.nombre) #sin validates

end

end
end

On Oct 2, 2007, at 9:12 PM, Rafa C. wrote:

entonces sí que podría centralizar el proceso en el controlador de
A, ya que el mero hecho de hacer B.new(params[:B]) debería disparar
las validaciones.

Eso es normal. Echale un vistazo a validates_associated y a los
metodos que AR ofrece para crear asociados partiendo del padre.

– fxn