rails formularios anidados ruby-on-rails nested-forms

ruby-on-rails - formularios anidados rails



cómo evitar guardar registros vacíos en un formulario de carriles anidados (4)

Estoy usando la gema nested_form para mi relación de AddressBook . Cuando el usuario borra el valor de un Addr existente, quiero eliminar ese Addr lugar de guardarlo con un value blanco

class Person < ActiveRecord::Base has_many :addrs, dependent: :destroy attr_accessible :name, :addrs_attributes accepts_nested_attributes_for :addrs, reject_if: :addr_blank, allow_destroy: true def addr_blank(a) valid? && a[:id].blank? && a[:value].blank? end class Addr < ActiveRecord::Base belongs_to :person attr_accessible :kind, :label, :value, :person_id

Mi método :reject_if funciona bien pero no me da todo lo que necesito

  1. valid? Mantiene mis Addrs en blanco alrededor a través de la validación.
  2. a[:id].blank? evita los rechazos cuando el usuario se queda en blanco y el registro existente

Ahora, necesito eliminar (en lugar de guardar) un Addr existente cuando el usuario borra el value . Además, estoy exponiendo Personas y Addrs a través de una API RESTful. Veo dos opciones posibles:

  1. params hash params para agregar el mágico _destroy=1 param. IOW, emula la actividad del usuario de presionar el botón de eliminar.
  2. Encapsule esto dentro del modelo de Addr manera que una actualización con un value blanco se considere efectivamente una eliminación.

Basado en el consejo aquí es cómo lo implementé:

people_controller.rb

def update @person = Person.find(params[:id]) @person.destroy_blank_addrs(params[:person]) respond_to do |format| ...

persona.rb

def destroy_blank_addrs(person_params) if valid? && person_params[:addrs_attributes] person_params[:addrs_attributes].each do |addr_params_array| addr_params= addr_params_array[1] addr_params[:_destroy] = ''1'' if !addr_params[:id].blank? && addr_params[:value].blank? end end end


Una tercera alternativa sería agregar una devolución de llamada before_save en Person que eliminará todas las direcciones que estén en blanco. Esta idea tiene algún mérito, pero probablemente no voy a seguir con ella.

De las dos opciones que presenta, no iré con el postprocesamiento de los parámetros. Funcionará, pero es demasiado trabajo. Además, el código del controlador se pondrá un poco más desordenado y creo firmemente en un controlador muy delgado.

La opción más fácil, en mi cabeza, es eliminar las direcciones en blanco después de guardar. Puede agregar la Person#remove_blank_addresses() y luego llamarla para guardar con éxito. No necesita pasar los parámetros, ya que puede iterar las direcciones y eliminar las que están en blanco. Tiene la desventaja de crear direcciones vacías y luego destruirlas, pero de todos modos necesitarías eso para actualizar a las personas.

Si estamos hablando de la solución más limpia (en mi opinión), introduciría una tercera clase que manejaría toda esa lógica y dejaría que el controlador la delegara. El controlador sería bastante fácil de probar de forma aislada y luego puede escribir una especificación de modelo que verifique todos los detalles esenciales. Es un poco más de trabajo y no puedo pensar en un buen nombre ahora ( PersonUpdater ?), Pero podría ser una idea en la que valga la pena pensar.


accepts_nested_attributes_for :addrs, allow_destroy: true, :reject_if => proc { |att| att[:name].blank? && attr[:description].blank? }


accepts_nested_attributes_for :addrs, allow_destroy: true, reject_if: -> { |attr| [name, description].any? &:blank? }


accepts_nested_attributes_for :addrs, allow_destroy: true, reject_if: :all_blank