Joh*_*hat 8 ruby ruby-on-rails
注意这最初是作为一个关于404错误的问题开始的,但现在问题是为什么我应用的补丁会产生影响.
如何获得缓存操作以在所有引发ActiveRecord :: RecordNotFound异常的请求上返回404,而不仅仅是第一个请求?
例如,如果你启动一个空的rails项目,添加一个Product model和controller,设置你的database.yml,在production.rb中设置你的缓存后端,rake db:migrate,然后在生产中启动并点击该站点现有对象,例如http:// localhost:3000/product/show/1234
class ProductController < ApplicationController
caches_action :show
def show
@product = Product.find(params[:id])
render :text => "asdf"
end
end
Run Code Online (Sandbox Code Playgroud)
第一次点击页面时,它会按预期返回404页面.但是,对该URL的每次后续匹配都会返回一个200 OK的空白页面.你怎么得到它每次返回404?
以下是CURL请求,后跟日志
~ $ curl -I http://0.0.0.0:3000/product/show/1234
HTTP/1.1 404 Not Found
Connection: close
Date: Mon, 20 Apr 2009 22:49:18 GMT
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Content-Length: 14097
~ $ curl -I http://0.0.0.0:3000/product/show/1234
HTTP/1.1 200 OK
Connection: close
Date: Mon, 20 Apr 2009 22:49:19 GMT
X-Runtime: 6
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Content-Length: 0
Run Code Online (Sandbox Code Playgroud)
第二个反应显然是错误的.
以下是2个请求的日志副本:
Processing ProductController#show (for 127.0.0.1 at 2009-04-20 17:35:24) [GET]
Parameters: {"id"=>"1234"}
ActiveRecord::RecordNotFound (Couldn't find Product with ID=1234):
app/controllers/product_controller.rb:6:in `show'
Rendering rescues/layout (not_found)
Processing ProductController#show (for 127.0.0.1 at 2009-04-20 17:35:30) [GET]
Parameters: {"id"=>"1234"}
Filter chain halted as [#<ActionController::Caching::Actions::ActionCacheFilter:0x23e36d4 @options={:cache_path=>nil, :store_options=>{}, :layout=>nil}>] rendered_or_redirected.
Filter chain halted as [#<ActionController::Filters::AroundFilter:0x23e3580 @kind=:filter, @options={:unless=>nil, :if=>nil, :only=>#<Set: {"show"}>}, @method=#<ActionController::Caching::Actions::ActionCacheFilter:0x23e36d4 @options={:cache_path=>nil, :store_options=>{}, :layout=>nil}>, @identifier=nil>] did_not_yield.
Completed in 12ms (View: 0, DB: 0) | 200 OK [http://0.0.0.0/product/show/1234]
Run Code Online (Sandbox Code Playgroud)
实际上,如果你将缓存的操作从缓存中拉出来,那里就会有一些空垃圾.
cache.fetch("views/0.0.0.0:3000/product/show/1234")
=> ["", nil, [], []]
Run Code Online (Sandbox Code Playgroud)
我在这做错了什么?
编辑
我已经确认Rails 2.1.2和2.2.2没有表现出这种行为,但2.3.2确实如此.(即旧版本不会将空响应存储到缓存中,并且它们确实会为后续请求抛出404)
我在测试边缘Rails时遇到问题,因为在启动服务器时加载它会导致以下错误:foobar/vendor/rails/activesupport/lib/active_support/dependencies.rb:440:in`load_missing_constant':uninitialized constant ActionController ::故障安全(NameError)
我已经对2-3稳定分支375e8976e3的当前负责人进行了测试,它也表现出这种行为.
编辑#2 我试图跟踪Rails代码库中发生更改的时间,以确定它是否是故意的.似乎这个看似无害的提交是bug开始的地方.
以下是二分的细节,其中404表示期望的行为,200表示不期望的行为.
2-3-stable branch
375e8976e3 - 200
b1c989f28d - 200
beca1f2e15 - 200
f1fff0a48 - 200
f1e20ce9a7 - 200
a5004573d8 - 200
2e1132fad8 - 200 - the difference seems to start at this commit
c69d8c043f - 404
d961592886 - 404
276ec16007 - 404
0efec6452 - 404
13c6c3cfc5 - 404
fb2325e35 - 404
2-2 stable
3cb89257b4 - 404
这是一个反转更改的补丁,当应用于标记v2.3.2.1,即dc88847e5ce392eed210b97525c14fca55852867时,修复了该问题.然而,我不够聪明,不知道为什么这个看似微不足道的变化实际上会有所作为!也许比我聪明的人可以对这种情况有所了解?
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 0facf70..0790807 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -1403,12 +1403,9 @@ module ActionController #:nodoc:
end
Base.class_eval do
- [ Filters, Layout, Benchmarking, Rescue, Flash, MimeResponds, Helpers,
- Cookies, Caching, Verification, Streaming, SessionManagement,
- HttpAuthentication::Basic::ControllerMethods, HttpAuthentication::Digest::ControllerMethods,
- RecordIdentifier, RequestForgeryProtection, Translation
- ].each do |mod|
- include mod
- end
+ include Filters, Layout, Benchmarking, Rescue, Flash, MimeResponds, Helpers
+ include Cookies, Caching, Verification, Streaming, SessionManagement
+ include HttpAuthentication::Basic::ControllerMethods, HttpAuthentication::Digest::ControllerMethods
+ include RecordIdentifier, RequestForgeryProtection, Translation
end
end
Run Code Online (Sandbox Code Playgroud)
编辑#3 补丁似乎也修复了上面显示的相关错误,其中"在XYms中完成(DB:Z)| 404找不到[ http://0.0.0.0/product/1234] "没有显示在日志.
编辑#4 上面的补丁破坏了ActionPack中的其他内容,因此我深入研究并生成了一个不会导致附带损害的问题.补丁和任何后续更新将在轨道灯塔
Gre*_*ell 16
它似乎include(X, Y, Z)实际上以不同的顺序运行include X; include Y; include Z.
下面我粘贴了在Ruby 1.8.6中实现Module#include方法的C代码.
static VALUE
rb_mod_include(argc, argv, module)
int argc;
VALUE *argv;
VALUE module;
{
int i;
for (i=0; i<argc; i++) Check_Type(argv[i], T_MODULE);
while (argc--) {
rb_funcall(argv[argc], rb_intern("append_features"), 1, module);
rb_funcall(argv[argc], rb_intern("included"), 1, module);
}
return module;
}
Run Code Online (Sandbox Code Playgroud)
即使你不熟悉Ruby的C内部,很明显这个函数有一个for循环向上迭代来检查所有参数的类型是否为T_MODULE,然后使用while循环向下迭代以实际包含模块 - 所以模块include(X, Y, Z)实际上会包含在订单中Z, Y, X.我还没有浏览过所有相关的Rails模块,但我想有一些依赖于顺序的东西,一旦切换包含顺序就开始失败了.
| 归档时间: |
|
| 查看次数: |
965 次 |
| 最近记录: |