Подтвердить что ты не робот

Как получить Rails build и fields_for для создания только новой записи и не включать существующие?

Я использую build, fields_for и accepts_nested_attributes_for, чтобы создать новую регистрационную записку в той же форме, что и новая регистрация (имеется много регистрационных заметок). Отлично.

Проблема: в форме редактирования для существующей регистрации я хочу создать новую регистрационную заметку, но я не хочу видеть поле для каждой из существующих регистрационных заметок.

У меня есть это

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

и этот

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

и в представлении я делаю это:

<%= 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 %>

и он создает пустую текстовую область для новой регистрационной заметки (хорошо) и каждую существующую регистрационную записку для этой регистрации (нет благодарности).

Есть ли способ создать новую заметку для этой регистрации и оставить только существующие?

4b9b3361

Ответ 1

РЕДАКТИРОВАТЬ. Мой предыдущий ответ (см. ниже) прослушивал меня, потому что он не очень приятный (он по-прежнему без проблем проходит все остальные registration_notes). После прочтения API немного больше, лучший способ получить поведение, которое требуется OP:

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

с:

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

fields_for необязательно принимает второй параметр, который является конкретным объектом для перехода к строителю (см. API), который встроен в строку. Вероятно, на самом деле лучше создать и передать новую ноту в контроллере, а не в форме (просто чтобы вывести логику из представления).


Оригинальный ответ (я был так близко):

Чтобы уточнить, вы хотите, чтобы ваша форма редактирования включала новую вложенную регистрационную заметку (и игнорировала любые другие существующие)? Я не тестировал это, но вы должны это сделать, заменив:

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

с:

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

РЕДАКТИРОВАТЬ: Хорошо, из моего собственного теста, который не работает, но вместо этого вы можете сделать:

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

Это добавит только текстовую область, если идентификатор регистрационной заметки равен нулю (т.е. он еще не сохранен).

Кроме того, я действительно проверил это первым, и он действительно работает;)

Ответ 2

Если вы хотите создать новую регистрационную форму в своем действии редактирования, вы можете просто создать экземпляр нового объекта registration_note. Прямо сейчас ваша форма предназначена для существующего объекта регистрации.

Я считаю, что это то, что вы хотите:

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

В вашем представлении вы должны передать скрытый параметр, который ссылается на идентификатор записи регистрации:

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

Теперь вы можете создать свою новую регистрационную заметку, которая принадлежит @registration. Убедитесь, что у вас есть столбец в таблице registration_notes, чтобы указать на регистрацию. Здесь вы можете узнать больше об ассоциациях: http://guides.rubyonrails.org/association_basics.html

Ответ 3

Большое вам спасибо за вашу помощь, как я сказал в своем посте, единственная проблема с подходом от "Zaid Crouch" (я не знаю, как сделать ссылку на пользователя хехе) заключается в том, что если форма имеет ошибку поля будут ясными и бум после перезагрузки страницы, у вас ничего не будет заполнено в вашей форме, и вы можете себе представить, сформируете ли вы, как 20 или 30 полей, которые, конечно, будут ужасным пользовательским интерфейсом.

Вот мое решение, которое работает с моделями проверки:

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 %>

Я использую simple_form в моем примере, если вы хотите увидеть то же самое, что работает с проверками и транзакциями, взгляните на полный пост здесь: http://elh.mx/ruby/using-simple_form-for-nested-attributes-models-in-a-has_many-relation-for-only-new-records/