Estoy trabajando en la implementación de un hiarchy de SEO, lo que significa que tengo que anteponer los parámetros para una acción de mostrar.Parámetros personalizados en la URL para mostrar la acción
El caso de uso es un sitio de búsqueda, donde la estructura de la URL es:
/cars/(:brand)/
=> una lista de páginas
/cars/(:brand)/(:model_name)?s=query_params
=> una búsqueda acción
/cars/:brand/:model_name/:variant/:id
=> una exhibición de autos acción
Mi El problema es hacer que las URL de acción de espectáculo funcionen sin tener que proporcionar:brand
, :model_name
y:variant
como argumentos individuales . Siempre están disponibles como valores en el recurso.
Lo que tengo: /cars/19330-Audi-A4-3.0-TDI
Lo que quiero /cars/Audi/A4/3.0-TDI/19330
Anteriormente, esto fue como el routes.rb
parecía:
# Before
resources :cars. only: [:show] do
member do
get 'favourize'
get 'unfavourize'
end
siguiente fue mi primer intento:
# First attempt
scope '/cars/:brand/:model_name/:variant' do
match ":id" => 'cars_controller#show'
match ":car_id/favourize" => 'cars_controller#favourize', as: :favourize_car
match ":car_id/unfavourize" => 'cars_controller#unfavourize', as: :unfavourize_car
end
Esto hace posible hacer:
cars_path(car, brand: car.brand, model_name: car.model_name, variant: car.variant)
Pero eso obviamente no es realmente ideal.
¿Cómo es posible configurar las rutas (y tal vez el método .to_param
?) De una manera que no sea una tarea tediosa cambiar todas las llamadas link_to
?
¡Gracias de antemano!
- ACTUALIZACIÓN -
con la sugerencia de @ tharrisson, esto es lo que he intentado:
# routes.rb
match '/:brand/:model_name/:variant/:id' => 'cars#show', as: :car
# car.rb
def to_param
# Replace all non-alphanumeric chars with - , then merge adjacent dashes into one
"#{brand}/#{model_name}/#{variant.downcase.gsub(/[^[:alnum:]]/,'-').gsub(/-{2,}/,'-')}/#{id}"
end
La ruta funciona bien, por ejemplo, /cars/Audi/A4/3.0-TDI/19930
muestra la página correcta. Generar el enlace con to_param
, sin embargo, no funciona. Ejemplo:
link_to "car link", car_path(@car)
#=> ActionView::Template::Error (No route matches {:controller=>"cars", :action=>"show", :locale=>"da", :brand=>#<Car id: 487143, (...)>})
link_to "car link 2", car_path(@car, brand: "Audi")
#=> ActionView::Template::Error (No route matches {:controller=>"cars", :action=>"show", :locale=>"da", :brand=>"Audi", :model_name=>#<Car id: 487143, (...)>})
Rails no parece saber cómo traducir el to_param en un enlace válido.
Esta es una pregunta muy buena y bien escrito. Creo que tengo una idea y quiero asegurarme de estar en el camino correcto (sin juego de palabras). ¿Es el caso que quieres poder usar 'cars_path (@car)' en tu link_to's y hacer que genere la buena URL jerárquica de tus vistas, pero también hacer que el enrutador reconozca las URL "parciales" (por ejemplo, '/ cars/Audi') como una solicitud para listar Audis? ¿O es un requisito adicional para el link_to ser contextualmente consciente (por ejemplo, crea vínculos a la variante de/cars /: de algunas acciones del controlador, pero la URL completa del coche de otras acciones del controlador? –
Gracias, @tharrison. Creo lo hiciste bien, quiero poder usar 'cars_path (@car)' en mi 'link_to'. La acción que se está desencadenando puede controlarse mediante restricciones en' routes.rb'. Esto significa que las URL de 'cars/Audi' no usa 'cars_path' sino algo así como' brand_path (marca: "Audi") '. –
OK, llegando allí, pero no lo tengo entonces :-). Si desea usar rutas con nombre como brand_path, el argumento sería una instancia del modelo de marca ... aunque podría ser como 'brand_path (@ car.brand)'. ¿Tiene un modelo de marca y recursos en las rutas para eso? –