Cambiar el nombre del parámetro: id en Routing resources for Rails

107

Miré a mi alrededor sobre cómo cambiar la ranura de parámetros dinámicos y encontré esta publicación que hace exactamente lo mismo. La publicación es https://thoughtbot.com/blog/rails-patch-change-the-name-of-the-id-parameter-in

Básicamente lo que hace es, si sigue las rutas:

map.resources :clients, :key => :client_name do |client|
  client.resources :sites, :key => :name do |site|
    site.resources :articles, :key => :title
  end
end

Estas rutas crean las siguientes rutas:

/clients/:client_name
/clients/:client_name/sites/:name
/clients/:client_name/sites/:site_name/articles/:title

Una solución es anular el def to_parammétodo en el modelo, pero quiero esto sin tocar el modelo en sí.

Pero dado que es para Rails 2.x, ¿cómo puedo lograr lo mismo para Rails 3?

Actualizar

Esta aplicación utiliza Mongoid. No AR. Por lo tanto, la gema amigable no se puede usar afaik.

Autodidacta
fuente

Respuestas:

192

Carriles 4 y 5

En Rails 4, :paramse agregó la opción, que parece hacer exactamente lo que estás buscando. Puede echar un vistazo al código de Rails 3 en comparación con el código de Rails 4 .

Detalles

Puede implementar esto fácilmente en su routes.rbarchivo:

# config/routes.rb

resources :posts, param: :slug

# app/controllers/posts_controller.rb

# ...
@post = Post.find_by(slug: params[:slug])
# ...

A partir del lanzamiento de Rails 4, esta funcionalidad está documentada en las Guías de Rails .

Carriles 3

Desafortunadamente, en Rails 3, se eliminó la :keyopción para resources, por lo que ya no puede cambiar fácilmente el nombre de las rutas creadas de esta manera simplemente pasando una opción adicional.

Detalles

Supongo que de alguna manera ya consiguió que la aplicación funcionara de la manera que deseaba el año pasado, pero buscaré la manera de obtener el efecto que describe en Rails 3 en routes.rb. Solo implicará un poco más de trabajo que el to_parammétodo. Todavía se puede definir parámetros personalizados en rutas definidas usando scopey match(o no lo tenga primos get, put, post, y delete). Simplemente escriba el nombre del parámetro que desea en el comparador:

get 'clients/:client_name', :to => 'clients#show', :as => client

scope 'clients/:client_name' do
  get 'sites/:name', :to => 'sites#show', :as => site
end

Tendría que agregar manualmente todas las rutas que resourcescrea automáticamente para usted, pero lograría lo que está buscando. También puede utilizar eficazmente la :controlleropción con bloques scopeadicionales scopepara eliminar parte de la repetición.


EDITAR (8 de mayo de 2014): Haga que sea más obvio que la respuesta contiene información para ambos Rails 3 y 4. Actualice los enlaces al código para ir a los números de línea exactos y confirmaciones para que funcionen por un período de tiempo más largo.

EDITAR (16 de noviembre de 2014): Rails 4 debería estar en la parte superior ahora e incluir información relevante, ya que ha sido la versión actual de Rails desde hace bastante tiempo.

EDITAR (9 de agosto de 2016): refleje que la solución todavía funciona en Rails 5 y actualice los enlaces obsoletos.

Joshhepworth
fuente
1
Entonces, básicamente, Rails3 creó la opción de recursos en el enrutador para estar tranquilo, pero debe anularse por el hecho de tener nombres de variables personalizados ... ¡Se siente poco convincente!
Augustin Riedinger
1
Aquí hay un backport de la paramopción para rieles 3: gist.github.com/sj26/44ef47fe8b98b46ee32d
sj26
Esto termina rompiendo los ayudantes de URL. Terminan generando una ruta normal basada en id si paso un objeto o quejándose de una tecla [: slug] faltante si paso la slug. ¿Alguna idea de cómo solucionarlo?
RonLugge
9
Para su información, si usa recursos anidados, el parámetro para el recurso principal será post_slug, lo que puede resultar confuso.
ghayes
4
Esto es realmente bueno, pero ¿qué puedo hacer si no quiero el nombre del parámetro de la identificación principal como post_post_id para el recurso anidado?
Asnad Atta
45

en Rails 4, pase la opción param para cambiar: id params. Por ejemplo resources :photos, param: :photo_name, generará / photos /: photo_name

bobzsj87
fuente
1

Si te entiendo bien, lo que quieres es tener el en client_namelugar de iden tu url, ¿verdad?

Puede hacerlo anulando el to_parammétodo en su modelo. Puede obtener más información aquí .

Mohit Jain
fuente
1
Como ya mencioné, tengo la restricción de no cambiar el modelo. ¿El ejemplo mencionado anteriormente no es compatible o está obsoleto en Rails 3?
Autodidacta
1

Hay una joya para eso, al igual que hay una joya para todo;)

He estado usando FriendlyId para este tipo de comportamiento en rieles 3.

Sin embargo, requerirá que agregue algún código a su modelo, como este:

class Client < ActiveRecord::Base
  has_friendly_id :name
end

... y si sus clientes no tienen nombres compatibles con URI, es posible que desee usar un slug para eso, lo que puede hacer has_friendly_id :name, :use_slug => true. Sin embargo, cuando use slugs, obviamente también deberá conservarlos en la base de datos.

Y como ya se mencionó, aún puede usar el to_paramtruco con rieles 3, como se documenta aquí . Sin embargo, encuentro FriendlyId un poco más versátil.

escarcha
fuente
Me gusta la identificación amigable y la he usado en muchos proyectos. En realidad, mi aplicación usa Mongoid. Y friendly_id no lo admite afaik. Y como ya mencioné, mi restricción es no cambiar el modelo.
Autodidacta
1
Si está usando mongoid, hay mongoid-slug para lograr esta funcionalidad. En realidad se usa to_param, pero también hace algunas otras cosas inteligentes en segundo plano. Encontré el enlace aquí: stackoverflow.com/questions/4744446/…
Frost
Me gustó esa joya. Hay otro slugoide similar . Pero como vengo diciendo, tengo la restricción de no modificar el modelo. Eso to_paramrompe mi parte frontal de la aplicación. En realidad, estoy buscando desesperadamente el enfoque de enrutamiento si tengo que cambiar mi API pero sin romper la parte Modelo y Frontend de la aplicación. ¿Por qué no puedo tener el enfoque de modificar las rutas solo como dije y la publicación de ejemplo para la versión anterior de rieles anterior?
Autodidacta
¿Ha intentado reescribir sus controladores para que use sus claves de ruta personalizadas? Por ejemplo @client = Client.find(:name => param[:client_name]en ClientsController#show? Aquello podría funcionar.
Frost
Client.where(:name => param[:client_name]).first, es decir.
Frost
0

En Rails 3 puedes cambiar el nombre de las claves de identificación usando una combinación de espacios de nombres y ámbitos como esta (aunque no muy agradable):

namespace :clients do
  scope "/:client_name" do
    namespace :sites do
      scope "/:name" do
         post "/:title" => "articles#create"
         ...
      end
    end
  end
end
Dominik Goltermann
fuente