如果社区能形成读源码的风气,相信对提高是大有好处的。
我昨天带着对下面代码的 respond_to 的疑问,参观(只能惭愧地这么说,实在看不大懂,感觉参观下也好)了一下 3.2 的 actionpack,没记错吧,我总是记不住那几个 active、action 模块。里面有个 mime_responds 文件,其中有两个 respond_to。猜测是 mixin 到 controller。
源码宫殿里陈列着各种奇怪的代码,散发出一些神秘的气息。元编程的技巧随处可见。不得不佩服老外能琢磨。
def index
@people = Person.all
respond_to do |format|
format.html
format.xml { render xml: @people }
end
end
#mime_responds.rb
def respond_to(*mimes, &block)
raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
if collector = retrieve_collector_from_mimes(mimes, &block)
response = collector.response
response ? response.call : default_render({})
end
end
相信很多人会和我一样,不是很理解这个写法,现在我基本是理解了,format 的调用估计是做个设置。
能否请高手对照源码解释下,两个 respond_to 是如何起作用的。
还想有一个设计相关的节点,页面设计、数据库设计等
没看过源码,乱猜一下。format 是请求的对象,html,xml 是实例方法 (或干脆是 method_missing),有一个实例变量 is_collected,一个实例方法来判断调用的格式,不是当前格式或 is_collected 就退掉。2 层的 block 啊。
两个respond_to
是不一样的,一个是 class 方法,和respond_with
配合起作用,respond_to 要先定义一些要相应地 mine 类型,并放在mimes_for_respond_to
中,等到 action 里调用 respond_with 的时候再做处理。
而那个实例方法,就是你代码里的那种,则是先用要相应地 mine 类型和 block 构造一个内部类 Collector https://github.com/rails/rails/blob/bfc34fc0050ce61650701676dd45553aa82214c0/actionpack/lib/action_controller/metal/mime_responds.rb#L466 ,之后就在 collector 的 context 里调用 block,由 collector 来处理响应了,所以可以仔细看一下 Collector 类的代码。
而其实 respond_with 也可以像实例方法 respond_to 那样 block 调用,也是类似的,只不过多了一个 mine 的查找 https://github.com/rails/rails/blob/bfc34fc0050ce61650701676dd45553aa82214c0/actionpack/lib/action_controller/metal/mime_responds.rb#L431
(只能当抛砖引玉了)
我这边在 3.2 里 用表单 remote:true 提交,返回的东西这样设置
format.js
format.json json:@obj
最终不会走 format.js,也就是 action.js.erb 只会执行 json 里的东西,返回一个 json 对象,除非我写成 `format.js text: "javascript balabala'" 测代码的时候写了中文,发现只有双引号才能 alert = =
怀疑是路由没有指定 (.format),于是我加上了 xxxx_path(format: 'js') 结果还是一样
匪夷所思
#13 楼 @palytoxin 大哥你在这里回帖是在干嘛。。。
你先在你的 format.js 里面显式 render 一下 action.js.erb。如果成功的话,就看看是不是你没有遵循某些命名规定,致使 rails 不知道你要输出的是 action.js.erb。
检查:你的 controller 和 method 的方法,以及 action.js.erb 放的位置有没有遵照约定。
#14 楼 @alsotang 囧 不是在讨论 respond_to 的读源码问题么= = 我只是提个问题,有空去翻下源码
这个问题的话,
format.json json:@obj
我把这行删掉就没问题了 format.js 就会生效
也就是说,只要没有 format.json, rails 是知道我要输出的是 action.js.erb( 噢,这个 action 是个指代,其实遇到问题的是 create.js.erb
检查:你的 controller 和 method 的方法,以及 action.js.erb 放的位置有没有遵照约定。
这是必须的,是没有问题的
题外:上次给人修 bug 遇到一个问题,各种路径都对,一直报 404,调了一个上午
最后发现是文件名不知道为什么在前面多了一个空格本来是'_partial.html.erb' ==> ' _partial.html.erb'
windows 的资源管理器还没办法重命名,说文件已存在。 不信试试在 cmd 下 rename foo.txt " foo.txt",恶心死。。。
#15 楼 @palytoxin 看看你的 remote: true 那个表单发出去的 request 的 accept 里面声明要接受的是什么 content-type
源码?是 C 的,还是 C++ 的,或是 ruby 的。
我跑题了,还是上面跑题了。
能读 C++ 源码的有几个。不读能深入理解元编程吗。
为什么有本书叫 python 源码剖析,而没有 ruby 的。
#17 楼 @zhouchongzxc 国外是有的,只是没翻译。不是有 Ruby 显微镜这本书么。 从实用来说,主要是 rails 的源码。 当然可以包括一切值得学习探讨的代码。
def iframe_handler @iframe_handler ||= DashboardIFrameHandler.new(@application_interaction_timeout) end
想知道这个 ||= 是做什么用的啊?谢谢各位!
#20 楼 @diorbrand 这个是说:如果那个 handler 是 nil,就执行 new。反之如果不是 nil,就保持不变。
||是或运算,x ||= y, 相当于 x = x || y
应该是这样写了。这个代码的可读性明显好些。
respond_to :html, :xml
def create
@user = User.new(params[:user])
flash[:notice] = 'User was successfully created.' if @user.save
respond_with(@user)
end