У меня есть приложение rails 4, которое имеет форму, которая выглядит так:
<%= form_for @store, :html => {:multipart => true} do |f| %>
<%= f.fields_for :products do |product| %>
<%= render partial: "edit_product_fields", locals: {product:product} %>
<% end %>
<%= f.submit %>
<% end %>
а частица edit_product_fields выглядит следующим образом:
<select>
<option value="Textbook" <% if product.type_of == "Textbook" %>selected<% end %>>Textbook</option>
<option value="Magazine" <% if product.type_of == "Magazine" %>selected<% end %>>Magazine</option>
<option value="Book" <% if product.type_of == "Book" %>selected<% end %>>Book</option>
</select>
Когда у меня есть такой код, я получаю ошибку:
undefined method 'type_of' for #<NestedForm::Builder:0x00000102304f78>
но если я изменю линию рендеринга (я просто сделал это менее явным, выбирая частичную :):
<%= render "edit_product_fields", locals: {product:product} %>
Я получаю сообщение об ошибке:
undefined local variable or method 'product' for #<#<Class:0x0000010235a248>:0x0000010684b3c0>
В вашем первом блоке кода у вас есть объект Builder
который хранится как product
.
К счастью, Builder
предоставляет object
метод, поэтому вы можете получить доступ к фактическому объекту, который он представляет в форме:
<select>
<option value="Textbook" <%= 'selected' if product.object.type_of == "Textbook" %>>Textbook</option>
<option value="Magazine" <%= 'selected' if product.object.type_of == "Magazine" %>>Magazine</option>
<option value="Book" <%= 'selected' if product.object.type_of == "Book" %>>Book</option>
</select>
undefined method type_of for #<Class:0x000001064bcf60>
product.object.class.name
или product.object.is_a? Textbook
вместо type_of
. Я даже не уверен, существует ли type_of
в Ruby или Rails.
Ну type_of
не является рубиновым методом. Похоже, что это попытка набрать проверку, хотя... Но проверка типа обычно недоверчива на языках с утиным языком. Во всяком случае, мы можем использовать Reld Form Helper вместо этого и сделать этот код однострочным. Но сначала...
Причина, по которой render
жалуется на undefined local variable or method
продукт undefined local variable or method
'' после вашего изменения, заключается в том, что вызов рендеринга ожидает, что первый аргумент будет частичным именем, а второй - хешем для локальных пользователей:
<%= render "partial_name", local1: "a", local2: "b" %>
... или он ожидает, что все это будет хешем:
<%= render partial: "partial_name", locals: { local1: "a", local2: "b" } %>
Теперь вернемся к помощнику формы.
То, что вы ищете, - это помощник выбора. Это делает возможным следующее:
<%= product.select :type_of, %w[Textbook Magazine Book] %>
И это будет отображать все те же html, что и в части вашего _edit_product_field.html.erb
. Таким образом, вы, вероятно, должны просто избавиться от частичного, чтобы сохранить время рендеринга и поместить его прямо в вашу форму.
Еще один, второстепенный момент. Это может быть менее запутанным, чтобы вызывать fields_for
переменной блока product_form
вместо product
. Это необходимо помнить, что это не объект Product, с которым вы имеете дело, а скорее объект Form Generator. Кроме того, вам не нужно указывать :multipart => true
в Rails 4 form - Rails знает, чтобы сделать форму многочастной, если у вас есть элемент загрузки файла внутри тела формы.
Так что все вместе:
<%= form_for @store do |f| %>
<%= f.fields_for :products do |product_form| %>
<%= product_form.select :product, %w[Textbook Magazine Book] %>
<% end %>
<%= f.submit %>
<% end %>
type_of
на самом деле поле в моей модели продукта. Я изменю свой вопрос, чтобы отразить это, извините.
<%= product_form.select :type_of, %w[Textbook Magazine Book] %>
. Тогда я думаю, что у вас есть победитель!
nested_form
, он не работал для меня. Поэтому я выбралcocoon
жемчужина