2011-02-18 7 views
9

Soy nuevo en rails y no estoy seguro de estar de acuerdo con la forma en que he hecho las cosas en algunos de los tutoriales que he realizado. El problema tiene que ver con la forma de manejar envíos de formularios no válidos. La forma habitual de hacer las cosas parecen ser:La forma correcta de manejar envíos de formularios no válidos en Rails

class ThingsController < ApplicationController 


    # POST /things 
    def create 

    @thing = Thing.new(params[:thing]) 

    if @thing.save 
     flash[:notice] = 'Thing created' 
     redirect_to(@thing) 
    else 
     render :action => :new 
    end 

    end 

Cuando @ thing.save falla, el usuario se presenta con la misma forma, pre-llenado de salida con los valores que acaba de introducir, junto con un destello de lo que pasó incorrecto. Hasta ahora todo va bien, excepto que ahora la URL ha cambiado de/cosas/nuevo a cosas /, lo que uno esperaría ver en su lugar.

Además, si el usuario actualiza la página, ahora está mirando la vista de índice. Si hace clic atrás, se le pedirá que vuelva a enviar el formulario, que siempre he tratado de evitar. Si redirecciona_ a (new_thing_path), se pierde el envío anterior del usuario, como son los mensajes de error.

Me doy cuenta de que RESTfully, este método puede ser "correcto", ya que la creación de un objeto cosa debería ser el resultado de POSTing a/things, pero en lo que respecta a la interfaz del usuario, no me preocupa particularmente.

que pude "manualmente" guardar el objeto @thing válida en la sesión del usuario, que se mostrará después de que le redirigir de nuevo a new_thing_path, pero que se siente como un truco. Parece que debería haber una "manera de hacer rails" para hacer exactamente eso.

Ideas?

+0

Tengo exactamente la misma queja sobre el núcleo de Rails, pero usted lo redactó mejor que yo :) Buena pregunta. – Andrew

Respuesta

3

Como ha encontrado, de forma predeterminada cuando especifica resources :things, la ruta de POST para crear una cosa nueva está en /things. Aquí está la salida para rake routes:

things GET /things(.:format)   {:action=>"index", :controller=>"things"} 
      POST /things(.:format)   {:action=>"create", :controller=>"things"} 
new_thing GET /things/new(.:format)  {:action=>"new", :controller=>"things"} 
edit_thing GET /things/:id/edit(.:format) {:action=>"edit", :controller=>"things"} 
    thing GET /things/:id(.:format)  {:action=>"show", :controller=>"things"} 
      PUT /things/:id(.:format)  {:action=>"update", :controller=>"things"} 
      DELETE /things/:id(.:format)  {:action=>"destroy", :controller=>"things"} 

Parece que usted quiere algo más parecido a esto:

create_things POST /things/new(.:format)  {:action=>"create", :controller=>"things"} 
     things GET /things(.:format)   {:action=>"index", :controller=>"things"} 
    new_thing GET /things/new(.:format)  {:action=>"new", :controller=>"things"} 
    edit_thing GET /things/:id/edit(.:format) {:action=>"edit", :controller=>"things"} 
     thing GET /things/:id(.:format)  {:action=>"show", :controller=>"things"} 
       PUT /things/:id(.:format)  {:action=>"update", :controller=>"things"} 
       DELETE /things/:id(.:format)  {:action=>"destroy", :controller=>"things"} 

Aunque no se recomienda, puede obtener este resultado con el siguiente recorrido:

resources :things, :except => [ :create ] do 
    post "create" => "things#create", :as => :create, :path => 'new', :on => :collection 
end 

También necesitaría modificar sus formularios para que sean POST a la ruta correcta.

Dicho todo esto, la descripción de las URL que tiene en su pregunta no suena bien. Usted enumera lo siguiente: Después de presentar una nueva thing (enviar un formulario en /things/new),

  1. Las URL cambia /things/new a /things
  2. clic en Atrás instrucciones para volver a presentar la forma
  3. Refrescante muestra things#index

Esto es no la funcionalidad que experimento en mis propias aplicaciones de Rails 3.En su lugar, me parece que: Después de presentar una nueva thing (enviar un formulario en /things/new),

  1. la URL cambia de /things/new a /things (esto es lo mismo)
  2. Al hacer clic en la espalda lleva al usuario de regreso a la forma -sometidas no (ninguna solicitud de un re-post)
  3. indicaciones refrescante para volver a presentar la forma (como se esperaba en mi opinión)
+1

Gracias Brandon. Esto es útil, aunque todavía no me importa la funcionalidad predeterminada. Creo que usaré la validación de JavaScript para evitarlo tanto como sea posible. – dearlbry

0

sé que esto es una cuestión de edad, pero Un enfoque con el que he estado jugando últimamente es enviar el formulario con AJAX, incluso si no lo requiere de otra manera. Esto le permite enviarlo a la acción de creación/actualización predeterminada en lo que respecta a las rutas, pero la URL en el navegador no cambia. La respuesta puede ser un simple 200 para el éxito con un enlace a la página/index o donde sea que redirija a un guardado exitoso, o una "400 bad request" con mensaje (s) de error si los datos no son válidos.

La mayor caída es que la visualización de los mensajes de error y los campos no válidos ahora es responsabilidad exclusiva de su lado del cliente javascript. Esto se convierte en un problema mucho más pequeño e incluso puede ser algo bueno una vez que esté utilizando algo como Backbone o KnockoutJS en el lado del cliente.

Cuestiones relacionadas