Nota Esto originalmente comenzó como una pregunta sobre errores 404, pero ahora es una pregunta por qué el parche que apliqué marcaría la diferencia.Cuál es la diferencia entre [X, Y, Z] .each {| m | incluye m} e incluye X, Y, Z?
¿Cómo se obtiene una acción en caché para devolver un 404 en todas las solicitudes que generan una excepción ActiveRecord :: RecordNotFound, no solo la primera solicitud?
Por ejemplo, si inicia un proyecto de rieles vacíos, agregue un modelo de Producto y controlador, configure su database.yml, configure su backend de caché en production.rb, rake db: migrate, luego inicie en producción y acceda al sitio para un objeto inexistente, por ejemplo http://localhost:3000/product/show/1234
class ProductController < ApplicationController
caches_action :show
def show
@product = Product.find(params[:id])
render :text => "asdf"
end
end
La primera vez que la página es golpeado, devuelve la página 404 como se esperaba. Sin embargo, cada hit posterior a esa URL devuelve una página en blanco con 200 OK. ¿Cómo consigues que regrese 404 todo el tiempo?
Éstos son las solicitudes CURL, seguido por la logs
~ $ 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
La segunda respuesta es claramente erróneo.
Aquí está una copia del registro de las solicitudes 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]
De hecho, si se tira de la acción en caché de la memoria caché, tiene algún tipo de basura vacío en ese país.
cache.fetch("views/0.0.0.0:3000/product/show/1234")
=> ["", nil, [], []]
¿Qué estoy haciendo mal aquí?
Editar
He confirmado que Rails 2.1.2 y 2.2.2 no presentan este comportamiento, pero lo hace 2.3.2. (es decir, las versiones anteriores no almacenan una respuesta vacía en la memoria caché y de hecho arrojan un 404 para las solicitudes posteriores)
Tengo problemas para realizar pruebas contra bordes de borde, ya que al cargarlo se produce el siguiente error al iniciar el servidor: foobar/vendedor/carriles/ActiveSupport/lib/active_support/dependencies.rb: 440: en `load_missing_constant ': ActionController constante sin inicializar :: Failsafe (NameError)
he probado contra la cabeza actual del 2 -3-stable branch, 375e8976e3, y también presenta este comportamiento.
Edit # 2 Intenté rastrear cuando ocurrió el cambio en la base de código de Rails para determinar si fue intencional. Parece que this seemingly innocuous commit es donde comienza el error.
Aquí están los detalles de la bisección, donde 404 indica el comportamiento deseado, 200 no deseado.
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
Aquí es un parche que invierte el cambio, que cuando se aplica a la etiqueta v2.3.2.1, es decir dc88847e5ce392eed210b97525c14fca55852867, soluciona el problema. Yo, sin embargo, no soy lo suficientemente inteligente como para comprender por qué este cambio aparentemente pequeño realmente marcaría la diferencia. Quizás alguien más inteligente que yo podría arrojar algo de luz sobre la situación?
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
Edición # 3 El parche parece solucionar también el error relacionado, mostrado anteriormente, donde el "completó en XYms (DB: Z) | 404 No se ha encontrado [http://0.0.0.0/product/1234]" no se presentaron en el registro.
Edición # 4 El parche anterior se rompió otras cosas en ActionPack, por lo que profundizó y generó una solución para el problema que no causa daños colaterales. El parche y las actualizaciones posteriores se encontrarán en the rails lighthouse
de hecho, eso parece razonable. Gracias por su investigación y visión! –