2009-04-20 21 views
8

これはもともと404エラーに関する質問として開始されましたが、今では、私が適用したパッチが違いを生むのはなぜかという疑問です。[X、Y、Z]の違いは何ですか?各{| m | m}を含み、X、Y、Zを含む?

最初のリクエストだけでなく、ActiveRecord :: RecordNotFound例外を発生させるすべてのリクエストで404を返すようにキャッシュされたアクションを取得するにはどうすればよいですか?

たとえば、空のrailsプロジェクトを開始する場合は、Productモデルとコントローラを追加し、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 

ページがヒットした最初の時間は、それは404ページを返します。ただし、そのURLに次々とヒットするたびに200 OKの空白のページが返されます。どのように毎回404を返すようにしますか?ここで

は、第二の反応は明らかに間違っている

~ $ 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 

ログ続いCURLリクエスト、です。ここで

が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] 

あなたがキャッシュからキャッシュされたアクションを引き出した場合、それはそこに空のゴミのいくつかの並べ替えを持っています。

cache.fetch("views/0.0.0.0:3000/product/show/1234") 
=> ["", nil, [], []] 

私はここで間違っていますか?

編集

私はRailsの2.1.2と2.2.2は、この動作を示さないことが確認できましたが、2.3.2はありません。 (古いバージョンは空のレスポンスをキャッシュに格納せず、実際には後続のリクエストに対して404を投げます)

これをロードすると、次のエラーが発生することがあります。サーバー: foobarに/ベンダー/レール/ activesupportの/ libに/ active_support/dependencies.rb:440: `load_missing_constant '内:初期化されていない定数ActionController ::フェイルセーフ(NameError)

私は2の現在のヘッドに対してテストしてみました-3安定分岐、375e8976e3であり、この挙動も示す。

編集#2 変更は、それは意図的だったかどうかを判断するためにRailsのコードベースで発生したとき、私は追跡しようとしました。 this seemingly innocuous commitはバグが始まる場所です。

ここで、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 

編集#3 パッチはまた、上記展示関連のバグ、修正しているようだ:|に表示されませんでした "XYms(DB Z)に完成しhttp://0.0.0.0/product/1234]が[404が見つかりません"ログ。

編集#4 上記のパッチはActionPackに他のものを壊したので、私は中に掘り下げおよび担保損害を生じさせない問題の修正プログラムを生成しました。パッチとそれ以降の更新は、

答えて

16

になります。include(X, Y, Z)は、実際にはinclude X; include Y; include Zとは異なる順序で動作しているようです。

以下、Module#includeメソッドを実装するCコードをRuby 1.8.6に貼り付けました。

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; 
} 

あなたはRubyのCの内部に慣れていない場合でも、それはこの関数はループのすべての引数の型がT_MODULEであることを確認するために上向きに反復処理していることをかなり明確だし、その後、反復whileループを使用していますモジュールを実際に含めるには下向きになるので、include(X, Y, Z)のモジュールは実際にはZ, Y, Xの順番で含まれます。問題のすべてのRailsモジュールを調べたことはありませんでしたが、インクルードの順序が入れ替わった後に失敗し始めた何らかの順序依存性があると思います。

+0

実際、これは妥当と思われます。あなたの研究と洞察に感謝します! –

関連する問題