validate validar rails formularios form campos asociaciones anidados ruby-on-rails validation activerecord nested

ruby-on-rails - formularios - validar campos rails



accept_nested_attributes_for validation de validaciĆ³n de asociaciĆ³n hija (6)

Al contrario de lo que sugiere Bigo, no siempre es aceptable guardar primero el objeto padre y luego los hijos. Por lo general, quiere asegurarse de que todos los objetos validen antes de comenzar a guardarlos. Eso le da al usuario la oportunidad de volver a editar el formulario de entrada y corregir cualquier error.

El problema que describes se solucionará en Rails 3.0. Hubiera publicado un enlace al ticket de Lighthouse, pero stackoverflow.com no lo permite porque soy un nuevo usuario (#fail). Pero por el momento, puede usar el complemento " parental_control ", que arreglará su "error".

Estoy usando accept_nested_attributes_for en uno de mis modelos de Rails, y quiero guardar los elementos secundarios después de crear el elemento primario.

El formulario funciona a la perfección, pero la validación está fallando. Por simplicidad, imagine lo siguiente:

class Project < ActiveRecord::Base has_many :tasks accepts_nested_attributes_for :tasks end class Task < ActiveRecord::Base belongs_to :project validates_presence_of :project_id validates_associated :project end

Y estoy corriendo:

Project.create!( :name => ''Something'', :task_attributes => [ { :name => ''123'' }, { :name => ''456'' } ] )

Al guardar el modelo del proyecto, la validación está fallando en las tareas porque no tienen un project_id (ya que el proyecto no se ha guardado).

Parece que Rails sigue el siguiente patrón:

  • Validar proyecto
  • Validar tareas
  • Guardar proyecto
  • Guardar tareas

El patrón debería ser:

  • Validar proyecto
  • En Pase: Guardar Proyecto y continuar ...
  • Validar tareas
    • En Pase: Guardar Tareas
    • En caso de error: Eliminar proyecto (¿retroceder quizás?)

Así que mi pregunta se reduce a: ¿Cómo puedo hacer que Rails ejecute el método project_id = (o project =) y la validación en los hijos (tareas) DESPUÉS de que el padre (proyecto) se haya guardado, pero NO guarde el modelo padre (proyecto) si algún niño (tarea) no es válido?

¿Algunas ideas?


Lamentablemente, ninguna de las sugerencias anteriores funciona para mí con Rails 2.3.5.

En mi caso, el proyecto en una tarea es siempre nulo si ambos se crean usando atributos anidados. Solo si elimino la validates_presence_of, la creación se realiza correctamente. La prueba de la unidad y el registro muestran que todo se creó correctamente.

Por lo tanto, ahora tendería a agregar restricciones al DB en lugar de Rails, ya que eso parece ser más confiable en primer lugar.


Simplemente podría crear el proyecto y solo agregar los proyectos si pasa la validación:

tasks = params.delete(:task_attributes) if Project.create(params) Project.update_attributes(:task_attributes => tasks) end

Ciao


Solo valide la relación, no la ID:

class Task < ActiveRecord::Base belongs_to :project validates_presence_of :project end

Tan pronto como se rellene la asociación, ActiveRecord considerará que la validación ha tenido éxito, independientemente de que el modelo se haya guardado o no. Es posible que también desee investigar el autoguardado para asegurarse de que el proyecto de la tarea siempre se guarde:

class Task < ActiveRecord::Base belongs_to :project, :autosave => true validates_presence_of :project end


Use :inverse_of y validates_presence_of :parent . Esto debería arreglar su problema de validación.

class Dungeon < ActiveRecord::Base has_many :traps, :inverse_of => :dungeon end class Trap < ActiveRecord::Base belongs_to :dungeon, :inverse_of => :traps validates_presence_of :dungeon end

http://apidock.com/rails/ActiveModel/Validations/HelperMethods/validates_presence_of

https://github.com/rails/rails/blob/73f2d37505025a446bb5314a090f412d0fceb8ca/activerecord/test/cases/nested_attributes_test.rb


Utilice esta respuesta para Rails 2; de lo contrario, consulte a continuación la respuesta de :inverse_of

Puede evitar esto al no verificar el project_id si el proyecto asociado es válido.

class Task < ActiveRecord::Base belongs_to :project validates_presence_of :project_id, :unless => lambda {|task| task.project.try(:valid?)} validates_associated :project end