Я начал искать источник в Rails 3.1, чтобы выяснить это, я подумал, что это будет проще, чем искать где-либо еще. Более ранние версии Rails должны быть похожими. Перейти в конец, если tl; др.
Когда вы звоните 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
.