Modificare il nome del parametro: id in Routing resources for Rails


107

Mi sono guardato intorno su come cambiare lo slot dei parametri dinamici e ho trovato questo post che fa la cosa esatta. Il post è https:// Thoughtbot.com/blog/rails-patch-change-the-name-of-the-id-parameter-in

Fondamentalmente quello che fa è, se seguono i percorsi:

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

Questi percorsi creano i seguenti percorsi:

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

Una soluzione è sovrascrivere il def to_parammetodo nel modello, ma lo voglio senza toccare il modello stesso.

Ma dal momento che è per Rails 2.x, come posso ottenere lo stesso risultato per Rails 3?

Aggiornare

Questa app utilizza Mongoid. Non AR. Quindi, la gemma amichevole non può essere usata afaik.

Risposte:


192

Rotaie 4 e 5

In Rails 4 è :paramstata aggiunta l' opzione, che sembra fare esattamente quello che stai cercando. Puoi dare un'occhiata al codice Rails 3 rispetto al codice Rails 4 .

Dettagli

Puoi facilmente implementarlo nel tuo routes.rbfile:

# config/routes.rb

resources :posts, param: :slug

# app/controllers/posts_controller.rb

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

A partire dal rilascio di Rails 4, questa funzionalità è documentata nelle Rails Guides .

Rotaie 3

Sfortunatamente, in Rails 3, l' :keyopzione per è resourcesstata rimossa, quindi non puoi più cambiare facilmente il nome per le rotte create in questo modo semplicemente passando un'opzione extra.

Dettagli

Presumo che tu abbia già in qualche modo ottenuto l'applicazione che funziona nel modo desiderato nell'ultimo anno, ma cercherò di ottenere l'effetto che descrivi in ​​Rails 3 in routes.rb. Richiederà solo un po 'più di lavoro rispetto al to_parammetodo. È ancora possibile definire i parametri personalizzati in percorsi definiti attraverso scopee match(o è cugini get, put, post, e delete). Scrivi semplicemente il nome del parametro che desideri nel matcher:

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

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

Dovresti aggiungere manualmente tutti i percorsi che resourcescrea automaticamente per te, ma otterresti quello che stai cercando. Puoi anche utilizzare efficacemente l' :controlleropzione con scopee scopeblocchi aggiuntivi per eliminare parte della ripetizione.


EDIT (8 maggio 2014): Rendi più ovvio che la risposta contiene informazioni sia per Rails 3 che per 4. Aggiorna i collegamenti al codice per andare ai numeri di riga esatti e ai commit in modo che funzionino per un periodo di tempo più lungo.

EDIT (16 novembre 2014): Rails 4 dovrebbe essere in cima ora e includere informazioni rilevanti poiché è stata la versione corrente di Rails da un po 'di tempo.

EDIT (9 agosto 2016): rifletti sul fatto che la soluzione funziona ancora in Rails 5 e aggiorna i collegamenti obsoleti.


1
Quindi, fondamentalmente, Rails3 ha creato l'opzione delle risorse nel router per essere riposante, ma deve essere sovrascritta per avere nomi di variabili personalizzati ... Sembra zoppo!
Augustin Riedinger

1
Ecco un backport paramdell'opzione per rails 3: gist.github.com/sj26/44ef47fe8b98b46ee32d
sj26

Questo finisce per rompere gli helper URL. Finiscono per generare un normale percorso basato sull'ID se passo un oggetto o mi lamento di una chiave [: slug] mancante se passo lo slug. Qualche idea su come rimediare?
RonLugge

9
Cordiali saluti, se utilizzi risorse nidificate, il parametro per la risorsa padre sarà post_slug, il che potrebbe creare confusione.
ghayes

4
Questo è davvero buono, ma cosa posso fare se non voglio il nome del parametro dell'ID genitore come post_post_id per la risorsa nidificata?
Asnad Atta

45

in Rails 4, passare l'opzione param per modificare: id params. Ad esempio resources :photos, param: :photo_name, genererà / photos /: photo_name


1

Se ti capisco bene, quello che vuoi è avere il client_nameinvece che idnel tuo URL, giusto?

Puoi farlo sovrascrivendo il to_parammetodo nel tuo modello. Puoi ottenere maggiori informazioni qui .


1
Come ho già accennato, ho il vincolo di non modificare il modello. L'esempio di cui sopra non è supportato o deprecato in Rails 3?
Autodidatta

1

C'è una gemma per questo, proprio come c'è una gemma per tutto;)

Ho usato FriendlyId per questo tipo di comportamento in rails 3.

Tuttavia, ti richiederà di aggiungere del codice al tuo modello, in questo modo:

class Client < ActiveRecord::Base
  has_friendly_id :name
end

... e se i tuoi clienti non hanno nomi compatibili con l'URI, potresti voler usare uno slug per quello, cosa che puoi fare con has_friendly_id :name, :use_slug => true. Quando si usano gli slug, ovviamente è necessario persistere anche nel database.

E come già accennato, puoi ancora usare il to_paramtrucco con rails 3, come documentato qui . Tuttavia, trovo FriendlyId un po 'più versatile.


Mi piace l'ID amichevole e l'ho usato in molti progetti. In realtà la mia app utilizza Mongoid. E friendly_id non lo supporta afaik. E come ho già detto, il mio vincolo è non cambiare il modello.
Autodidact

1
Se stai usando mongoid, c'è mongoid-slug per ottenere questa funzionalità. In realtà usa to_param, ma fa anche altre cose intelligenti in background. Ho trovato il link qui: stackoverflow.com/questions/4744446/…
Frost

Mi piaceva quella gemma. C'è un altro slugoid simile . Ma come ho detto ho il vincolo di non modificare il modello. Questo to_paraminterrompe la mia parte front-end dell'app. In realtà sto cercando disperatamente l'approccio di routing è che devo cambiare la mia API ma senza rompere la parte Model e Frontend dall'app. Perché non posso avere l'approccio di modificare le rotte solo come avevo dichiarato e il post di esempio per la versione precedente dei binari sopra ???
Autodidatta

Hai provato a riscrivere i controller in modo che utilizzi le chiavi di percorso personalizzate? Ad esempio @client = Client.find(:name => param[:client_name]in ClientsController#show? Potrebbe funzionare.
Frost

Client.where(:name => param[:client_name]).first, questo è.
Frost

0

In Rails 3 puoi rinominare le chiavi id usando una combinazione di namespace e scope come questa (non molto carina però):

namespace :clients do
  scope "/:client_name" do
    namespace :sites do
      scope "/:name" do
         post "/:title" => "articles#create"
         ...
      end
    end
  end
end
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.