text_field_tag tag rails form_with form_for form for fields ruby-on-rails

ruby-on-rails - tag - form_with rails 5



¿Cómo obtener Rails build y fields_for para crear solo un nuevo registro y no incluir los existentes? (4)

Como Heriberto Pérez señaló correctamente, la solución en la respuesta más votada simplemente descartará todo si hay un error de validación en uno de los campos.

Mi enfoque es similar al de Heriberto pero sin embargo un poco diferente:

Modelo:

class Registration < ActiveRecord::Base has_many :registration_notes accepts_nested_attributes_for :registration_notes # Because 0 is never 1 this association will never return any records. # Above all this association don''t return any existing persisted records. has_many :new_registration_notes, -> { where(''0 = 1'') } , class_name: ''RegistrationNote'' accepts_nested_attributes_for :new_registration_notes end

Controlador:

class RegistrationsController < ApplicationController before_action :set_registration def edit @registration.new_registration_notes.build end private def set_registration @registration = Registration.find(params[:id]) end def new_registration_params params.require(:registration).permit(new_registrations_attributes: [:content]) end end

Ver:

<%= form_for @registration do |r| %> <%= r.text_field :foo %> <%= r.text_field :bar %> <%= r.fields_for :new_registration_notes do |n| %> <%= n.text_area :content %> <% end %> <% end %>

Estoy usando build , fields_for , y accepts_nested_attributes_for para crear una nueva nota de registro en el mismo formulario que un nuevo registro (tiene muchas notas de registro). Estupendo.

Problema: en el formulario de edición para el registro existente, quiero que se cree otra nueva nota de registro, pero no quiero ver un campo para cada una de las notas de registro existentes.

tengo esto

class Registration < ActiveRecord::Base attr_accessible :foo, :bar, :registration_notes_attributes has_many :registration_notes accepts_nested_attributes_for :registration_notes end

y esto

class RegistrationsController < ApplicationController def edit @registration = Registration.find(params[:id]) @registration.registration_notes.build end end

y en la vista estoy haciendo esto:

<%= form_for @registration do |r| %> <%= r.text_field :foo %> <%= r.text_field :bar %> <%= r.fields_for :registration_notes do |n| %> <%= n.text_area :content %> <% end %> <% end %>

y está creando un área de texto en blanco para una nueva nota de registro (buena) y cada nota de registro existente para esa inscripción (no, gracias).

¿Hay una manera de crear solo una nueva nota para ese registro y dejar las existentes solo?


Muchas gracias por su ayuda, como dije en mi publicación, el único problema con el enfoque de "Zaid Crouch" (no sé cómo hacer una referencia a un usuario jeje) es que si el formulario tiene campos de error, el formulario estará claro y en auge después de la recarga de la página, no tendrá nada completado en su formulario y puede imaginar si su formulario es de 20 o 30 campos, lo que sería una experiencia terrible para el usuario, por supuesto.

Aquí está mi solución que funciona con modelos de validación:

class Registration < ActiveRecord::Base attr_accessible :foo, :bar, :registration_notes_attributes has_many :registration_notes has_one :new_registration, class_name: ''RegistrationNote'' accepts_nested_attributes_for :new_registration end class RegistrationsController < ApplicationController def edit @registration = Registration.find(params[:id]) @registration.build_new_registration end end <%= form_for @registration do |r| %> <%= r.text_field :foo %> <%= r.text_field :bar %> <%= r.fields_for :new_registration do |n| %> <%= n.text_area :content %> <% end %> <% end %>

Estoy usando simple_form en mi ejemplo si desea ver el mismo trabajo con validaciones y transacciones, vea la publicación completa aquí: http://elh.mx/ruby/using-simple_form-for-nested-attributes-models-in-a-has_many-relation-for-only-new-records/


Si desea crear un nuevo formulario de registro en su acción de edición, simplemente puede crear una instancia de un nuevo objeto registration_note. En este momento, su formulario es para el objeto de registro existente.

Creo que esto es lo que quieres:

class RegistrationsController < ApplicationController def edit @new_registration_note = RegistrationNote.new @registration = Registration.find(params[:id]) @registration.registration_notes.build end end

En su opinión, debe pasar un parámetro oculto que haga referencia al ID de registro de registro:

<%= form_for @new_registration_note do |r| %> <%= r.hidden_field :registration_id, :value => @registration.id %> <%= r.text_area :content %> <% end %>

Ahora, puede crear su nueva nota de registro que pertenece a @registration . Asegúrese de tener una columna en su tabla registration_notes para apuntar al registro. Puede leer más sobre las asociaciones aquí: http://guides.rubyonrails.org/association_basics.html


EDITAR : Mi respuesta anterior (ver más abajo) me estaba molestando porque no es muy buena (aún se repite sin necesidad por todas las demás notas de registration_notes ). Después de leer el API un poco más, la mejor manera de obtener el comportamiento que quería el OP es reemplazar:

<%= r.fields_for :registration_notes do |n| %>

con:

<%= r.fields_for :registration_notes, @registration.registration_notes.build do |n| %>

fields_for toma opcionalmente un segundo parámetro que es el objeto específico para pasar al constructor ( ver la API ), que se construye en línea. Probablemente sea mejor crear y pasar la nueva nota en el controlador en lugar de hacerlo en la forma (solo para sacar la lógica de la vista).

Respuesta original (estaba tan cerca):

Solo para aclarar, ¿desea que su formulario de edición incluya una nueva nota de registro anidada (e ignore cualquier otra existente)? No he probado esto, pero deberías poder hacerlo reemplazando:

<%= r.fields_for :registration_notes do |n| %>

con:

<%= r.fields_for @registration.registration_notes.build do |n| %>

EDIT : Está bien, de una prueba rápida que no funciona, pero en su lugar puedes hacer:

<%= r.fields_for :registration_notes do |n| %> <%= n.text_area :content if n.object.id.nil? %> <% end %>

Esto solo agregará el área de texto si el ID de la nota de registro es nulo (es decir, aún no se ha guardado).

Además, en realidad probé esto primero y funciona;)