我正在关注Getting Started with Rails教程。
为view
create new article
生成controller
时,我使用:
案例1 ::article
<%= form_for :article do |f| %>
并得到错误No route matches [POST] "/articles/new"
我认为它应该是[POST] "/articles
案例2 我更改为:@artical
<%= form_for @article do |f| %>
没关系。
请注意,在案例1 中,submit button
的文字为:Save article
,在案例2
Create article />
它与This SOF answer的方式相反
这对我来说太模糊了!那么有人可以帮我解释一下吗?
这是我的source code on github
答案 0 :(得分:1)
form_for :article
创建了一个表单,但提交的默认网址为/articles/new
用于显示要提交的表单的文章的动作new
,而不是处理创建新文章
=&GT; resources :articles
会将其与GET
方法
您可以为该表单指定一个网址,或更改请求方法(不推荐)
<%= form_for :article, url: articles_path do |f| %>
答案 1 :(得分:1)
这是Rails的工作原理,所以基本上,你应该将一个对象传递给form_for
。
查看源代码后,在这里发生了什么。
将对象传递给form_for
时,action
将使用:
url_for(polymorphic_path(@object))
如果对象是未保留的文章,则为/articles
;如果对象为持久文章,则为/articles/:id
。
当您传递字符串或符号时,action
会调用url_for
在您的情况/articles/new
中使用空哈希,产生当前路径。请注意,如果您显示表单,请说/articles/custom
,路径为/articles/custom
。
对于按钮,如果传递对象,则提交输入值将为
I18n.t('helpers.submit.create')
或I18n.t('helpers.submit.update')
取决于您的模型是否持久化。但是,如果您传递字符串或符号,则值为I18n.t('helpers.submit.submit')
。
以下是Rails来源的相关代码行。
# actionview/lib/action_view/helpers/form_helper.rb#L422
def form_for(record, options = {}, &block)
# .....
when String, Symbol
object_name = record
object = nil
else
object = record.is_a?(Array) ? record.last : record
raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object
object_name = options[:as] || model_name_from_record_or_class(object).param_key
apply_form_for_options!(record, object, options)
end
# .....
html_options = html_options_for_form(options[:url] || {}, html_options)
form_tag_with_body(html_options, output)
end
# actionview/lib/action_view/helpers/form_helper.rb#L451
def apply_form_for_options!(record, object, options) #:nodoc:
# ....
options[:url] ||= if options.key?(:format)
polymorphic_path(record, format: options.delete(:format))
else
polymorphic_path(record, {})
end
end
# actionview/lib/action_view/helpers/form_tag_helper.rb#L840
def html_options_for_form(url_for_options, options)
options.stringify_keys.tap do |html_options|
# ....
html_options["action"] = url_for(url_for_options)
# ....
end
end
# actionview/lib/action_view/helpers/form_helper.rb#L1873
def submit_default_value
object = convert_to_model(@object)
key = object ? (object.persisted? ? :update : :create) : :submit
# .....
defaults = []
defaults << :"helpers.submit.#{object_name}.#{key}"
defaults << :"helpers.submit.#{key}"
defaults << "#{key.to_s.humanize} #{model}"
I18n.t(defaults.shift, model: model, default: defaults)
end
# locale/en.yml#L142
helpers:
select:
prompt: Please select
submit:
create: Create %{model}
submit: Save %{model}
update: Update %{model}
对于操作,您可以看到在传递字符串时未调用apply_form_for_options!
,因此options[:url]
仍为nil
。当您传递对象时,apply_form_for_options!
会将options[:url]
设置为polymorphic_path(@object)
(如果未设置)。然后将其传递给html_options_for_form
,其中action
设置为应用url_for
值。
对于提交值,您可以看到如何根据表单目标是否为对象来获取密钥,然后进行翻译。