Ответ 1
Я поучаствовал в источнике Rails 3.1, чтобы разобраться в этом, я понял, что это будет проще, чем поиск в другом месте. Ранние версии Rails должны быть похожими. Перейти к концу, если tl; dr.
Когда вы вызываете form_for(@user)
, вы заканчиваете это:
def form_for(record, options = {}, &proc)
#...
case record
when String, Symbol
object_name = record
object = nil
else
object = record.is_a?(Array) ? record.last : record
object_name = options[:as] || ActiveModel::Naming.param_key(object)
apply_form_for_options!(record, options)
end
И поскольку @user
не является ни строкой, ни объектом, вы проходите ветвь else
и в apply_form_for_options!
. Внутри apply_form_for_options!
мы видим следующее:
as = options[:as]
#...
options[:html].reverse_merge!(
:class => as ? "#{as}_#{action}" : dom_class(object, action),
:id => as ? "#{as}_#{action}" : dom_id(object, action),
:method => method
)
Обратите внимание на этот фрагмент кода, он содержит как источник вашей проблемы, так и решение. Метод dom_id
вызывает record_key_for_dom_id
, который выглядит следующим образом:
def record_key_for_dom_id(record)
record = record.to_model if record.respond_to?(:to_model)
key = record.to_key
key ? sanitize_dom_id(key.join('_')) : key
end
И вот ваш вызов to_key
. Метод to_key
определяется ActiveRecord::AttributeMethods::PrimaryKey
, и поскольку вы не используете ActiveRecord, у вас нет метода to_key
. Если у вас есть что-то в вашей модели, которое ведет себя как первичный ключ, тогда вы можете определить свой собственный to_key
и оставить его на этом.
Но если мы вернемся к apply_form_for_options!
, мы увидим другое решение:
as = options[:as]
Итак, вы можете предоставить :as
вариант form_for
для создания идентификатора DOM для вашей формы вручную:
<%= form_for(@user, :as => 'user_form') do |f| %>
Вам нужно убедиться, что значение :as
было уникальным на странице.
Резюме:
- Если ваша модель имеет атрибут, который ведет себя как первичный ключ, затем определите свой собственный метод
to_key
, который возвращает его. - Или поставьте соответствующую опцию
:as
наform_for
.