Estoy tratando de implementar un sistema genérico de vanity url en Rails 3. Genérico en el sentido de que la url de tocador no está vinculada a un modelo específico. Es similar a la gema Vanities donde tengo un VanityUrlController
que se ve afectado por todas las URL de vanidad. La diferencia es que no quiero hacer una redirección externa de foo.com/username
a foo.com/users/1
o foo.com/product-name
a foo.com/products/1
. Quiero que la url de tocador permanezca y que VanityUrlContoller haga un redireccionamiento interno que imite la acción de mostrar correspondiente.Redirecciones internas con raíles 3
Sé a qué controlador y acción quiero enviar el redireccionamiento interno, pero tengo problemas para despacharlo. Aquí es donde estoy en este momento:
TargetController.new.process("show", request.env)
parece comenzar a procesar el nuevo "petición", pero hay piezas clave que falta ... como la solicitud objeto real.
Cualquier idea o sugerencia sería muy apreciada.
Actualización:
me encontré con el método de despacho en ActionController que parece conseguirme un poco más lejos.
TargetController.new.dispatch("show", request)
Tengo dos problemas con esto, 1) que está catalogado como un método API privada así que si hay otra manera de hacer esto, prefiero eso, y 2) a pesar de que está prestando el espectáculo plantilla para el TargetController, se queja de "Plantilla faltante vanity_urls/show".
ACTUALIZACIÓN
Aquí es lo básico de la solución que se nos ocurrió. Hacemos otras cosas como forzar codificaciones y verificar algunas otras cosas específicas de la aplicación, pero esto debería ser todo lo que necesita para ponerse en marcha.
Esto va en la parte inferior de su archivo routes.rb
para que sus rutas de vanidad no toquen sus otras rutas con nombre.
# Vanity routes.
match ':id', :as => 'vanity', :to => proc { |env|
id = env["action_dispatch.request.path_parameters"][:id]
vain_object = <method to find the object you want to display>
if vain_object.nil?
# render your 404 page
'application#404'
else
model = vain_object.class.model_name
# figure out the controller you want to go to
controller = [model.pluralize.camelize,"Controller"].join.constantize
# reset the :id parameter with the id of the object to be displayed
env["action_dispatch.request.path_parameters"][:id] = vain_object.id
# do your internal redirect
controller.action("show").call(env)
end
}
también querrá tener cuidado al crear las rutas de tocador, de manera que no choquen con los otros controladores. Algunas otras cosas útiles a conocer son:
Rails.application.routes.routes.any? { |r| r.requirements[:controller] == vanity_url }
que le indica si su vanity_url
tiene el mismo nombre que un controlador de corriente.
Rails.application.routes.recognize_path("/#{vanity_url}", :method => :get)
Lo que indica si esto ya se asigna a algo.
Claro, hay un par de cortes en el camino, pero funciona a las mil maravillas.
Aquí hay una opción similar con la lambda extraída y las restricciones aplicadas http://stackoverflow.com/questions/5641786/testing-rack-routing-using-rspec – Agustin