环境如下: controllers/events_controller.rb
def new
@event1 = Event.new
end
def create
@event = Event.new(params[:event])
@event.save
redirect_to :action => :index
end
events/new.html.erb:
<%= form_for @event1, :url => { :controller => 'events', :action => 'create' } do |f| %>
<%= f.label :name, "Name" %>
<%= f.text_field :name %>
<%= f.label :description, "Description" %>
<%= f.text_area :description %>
<%= f.submit "Create" %>
<% end %>
我不明白,def create 里面,new(params[:event]) ,event 这个变量从哪里来的?
@lgn21st 赞。偶是一个 ruby 新手,以前也没多少语言基础,上次在知乎问的一个问题很基础,高手看了可能觉得很低级,最后有人回答得知是 ruby 版本的原因,有时老手的一句指点真的很重要。
#14 楼 @lin_style 约定大于配置这个对,我也不是特别明白内部实现,我对 rails 代码还是有点敬畏,不太有信心看 我个人理解
def new
@event1 = Event.new
end
form 的@event1,要看 new action,而不是 create 的 这个里头,你的@event就是一个 Event 的一个实例,空的 所以如果你的这个 form 只是为了 new 和 create,你的 form_for 第一个参数完全可以写成 Event.new
但是大家一般都写成@event的原因是因为,修改和创建一个 model 一般都是用的相同的 partial, 你可能会有这样的代码
def edit
@event1 = Events.find(params[:id])
end
这样的话,你的 edit action 触发的时候就不会有这个记录的默认数据在表单中
如果在 lz 的表单里,name 填写 somename,在 description 里填写 somedescripition,那么点击表单后,浏览器会发送一个 POST 请求给服务器,这 POST 请求的 body 会是如下内容(这是浏览器干的,和 rails 没关系):
commit=Create&event%5Bdescription%5D=somedescription&event%5Bname%5D=somename
服务器在接收到这请求后,就会去解析这个 body。比如,Rack 会这样解析这个字符串(见 https://github.com/rack/rack/blob/master/lib/rack/request.rb 中的 Rack::Request#params
方法)
s = "commit=Create&event%5Bdescription%5D=somedescription&event%5Bname%5D=somename"
Rack::Utils.parse_nested_query(s)
# => {"commit"=>"Create", "event"=>{"description"=>"somedescription", "name"=>"somename"}}
假设一个叫 #params
的方法的返回值,是上面的 Hash,那么就可以通过 params['event'] 得到用户输入的表单数据。
Rails-3 里,就是使用类似方法来解析 GET 请求的查询串和 POST 请求的 body,只不过增加了一些高级功能(比如既可以用字符串作为 Hash 的 key,也可以用 Symbol 作为 key)。具体可以参考 ActionDispatch::Http::Parameters#parameters
,#params
方法是 #parameters
的别名。
由于大多数 ruby web application 都是基于 Rack,而这些 application 大都基于Rack::Utils.parse_nested_query
方法来解析请求参数。这就形成了这种参数格式的惯例。
其实这个问题挺简单的
params 就是 http request 发过来的 paramter. params[:event] 就是 http request 发过来的 parameter 里面叫做:event 的。
这个可以是从 form 里面来的,也可以是 query string 里的来的。
这个跟前端这个 request 怎么生成的其实关系不大。 不光 rails,任何 web 框架,甚至以前的 cgi 等都得跟 request 打交道。
如果这部分不清楚的话,最好还是学习一下 http 的基本知识。
#15 楼 @lin_style form_tag 生成的 name="event[name]" 是更根据 @event1 的类名来的,跟你去什么对象名称没有关系。
这个跟 http 的基础知识真没什么关系。我改成 event1 就是验证下,这个跟参数名有没关系,后来发现没关系,所以才来论坛问的。我也不关心 event 到底哪儿来的,我只关心 event 命名的依据而已。我也知道习惯优于配置,我也看到了 http 中的源码,但是这个习惯不是凭空而降的,所以我才追问习惯的依据在哪里?
谢谢 #17 楼 @zhangyuan 的源码解析
目前看就 #20 楼 @huacnlee 回答了我的疑问,我也是怀疑是不是和我的类名有关系,比如我叫 events_controller.rb,就取前面的 event.现在只要有个权威人士说明确实是这个,我就满足了。
或许我描述得不够清楚,让大家回答偏了,抱歉。
form_for 的参数@event1获得了你的类,然后 f.text_field :name 里,f 就代表这个实例的信息,这里获得了 event,最后形成的 input 的 name 就是 event[name] 这目的是为了让你在 action 里接受容易些。 event[name]、event[description] 在 action 里 params[:event] 就可以获得{:name=>"xxx",:description=>"xxx"} 说白了,约定好,你就省事了。。。偶以前用 dotnet,老点的版本的,就得把提交每一个参数都写一遍。。。。