È corretto usare una chiave non primaria come id in una risorsa di rotaie?

3

Mi sto preparando a configurare una risorsa per alcune nuove chiamate API alla mia applicazione rails.

Sto pianificando di chiamare i dispositivi delle risorse, cioè

resources :devices

Questo rappresenterà i dispositivi mobili Android

So che questo mi procurerà percorsi come

Dispositivi GET /: id

Nella maggior parte dei casi: id sarebbe un numero intero che rappresenta la chiave primaria e nel controller useremo: id come tale:

GET devices/1
@device = Device.find(params[:id])

In questo caso vorrei usare: id come google_cloud_messaging_reg_id

Quindi vorrei avere richieste come questa:

GET devices/some_long_gcm_id

e poi nel controller, solo noi params[:id] per cercare il dispositivo tramite l'ID di registrazione gcm. Questo sembra più naturale, dal momento che il dispositivo saprà che è id gcm piuttosto che è l'ID intero dei binari. Ci sono dei motivi per evitare di farlo?

-------------------------------------------- -------------------------

UPDATE:

La mia preoccupazione iniziale era che vedere un percorso (tramite rake route) di / devices /: id o guardare il controller e vedere i parametri [: id] sarebbe stato confuso poiché la maggior parte avrebbe dovuto assumere: id era la chiave primaria intera.

Dopo averci pensato un po 'di più e aver letto la risposta di Idan Arye in basso, il mio pensiero attuale è quello di creare percorsi come mostrato di seguito. Questo mi procurerà percorsi (tramite percorsi rake) che assomigliano a questo:

GET    /api/v1/android_devices/:gcm_reg_key(.:format) 

che a mio avviso chiarisce in qualche modo che: gcm_reg_key potrebbe non essere un numero intero di chiavi primarie . E nel controller il parametro sarebbe

params[:gcm_reg_key]

Ancora una volta, penso che questo chiarisca in qualche modo che il parametro non può essere una chiave primaria intera (la convenzione sarebbe params [: id])

Qualsiasi altro suggerimento o suggerimento è benvenuto.

match '/android_devices/:gcm_reg_key', to: 'android_devices#show' , via: :get, as: 'android_device'
match '/android_devices/:gcm_reg_key', to: 'android_devices#update', via: :post, as: 'android_device_create'
match '/android_devices/:gcm_reg_key', to: 'android_devices#update', via: :patch, as: 'android_device_modify'
match '/android_devices/:gcm_reg_key', to: 'android_devices#destroy', via: :delete, as: 'android_device_destroy'
resources :android_devices , only: [:create, :index]
    
posta nPn 30.05.2014 - 01:00
fonte

2 risposte

4

In realtà, ci sono 3 ragioni:

  1. convenzione
  2. convenzione
  3. convenzione

La convenzione è importante, perché rende più facile per gli altri programmatori capire il tuo codice. In RoR è ancora più importante, dal momento che molte strutture del framework e plugin di terze parti stanno assumendo che tu stia seguendo la convenzione. Spesso offrono un'interfaccia di configurazione che puoi utilizzare in caso di violazione della convenzione, ma questo renderà il loro utilizzo più dettagliato, complicato e soggetto a errori.

Quindi, dovresti interrompere la convenzione solo se hai una buona ragione per farlo - e questo non è uno, perché c'è un'alternativa molto più semplice: usare i parametri GET!

Invece di dirottare l'azione show , crea una nuova rotta, ad es. %codice%. Quell'azione accetterà l'ID GCM come parametro GET come parte del percorso, quindi il percorso sarà:

GET devices/find_and_show?gcm_id=<some_long_gcm_id>

Il metodo dovrebbe trovare find_and_show di Device , e il resto potrebbe essere condiviso con il normale metodo gcm_id o anche delegato ad esso con un reindirizzamento.

In questo modo non stai violando alcuna convenzione, stai rendendo chiaro che stai cercando per ID GCM piuttosto che per PK e se vuoi consentire il recupero tramite altri identificatori univoci puoi semplicemente fare il supporto di show più parametri GET.

E sì, renderà gli URL più lunghi, ma non è come se gli umani digitassero questi URL ...

    
risposta data 30.05.2014 - 01:49
fonte
1

Devi fare una distinzione tra il tuo database e l'url, che in realtà è una specie di API o anteriore ai tuoi dati. Non vi è alcun obbligo che quello che è l'ID nell'url, corrisponde all'ID nel database.

In realtà, posso dare due buoni motivi per differenziare questo ID:

  1. Un hacker potrebbe indovinare l'url degli altri dispositivi esistenti, semplicemente incrementando / decrementando l'id. A seconda del tipo di sito che hai, questo potrebbe o potrebbe non essere pertinente.
  2. Un url potrebbe essere più facilmente ricordato se è interamente leggibile / significativo. Ti piace qualcosa come /blogs/:blog_title . E il tuo caso si applica perfettamente perfettamente.

Quindi personalmente ho fatto quasi esattamente quello che hai detto, senza cambiare le rotte.

Per assicurarti che tutti gli helper dei link continuino a funzionare, devi solo sostituire la funzione to_param per un modello ( documenti ).

Quindi nel tuo caso

class Device < ActiveRecord::Base

  def to_param
    gcm_reg_key
  end

end

e quindi puoi ancora scrivere device_path(@device) e formerà correttamente l'URL.

Nel tuo controller devi solo scrivere

def show
  @device = Device.find_by(gcm_reg_key: params[:id])
end

e quindi mantieni i tuoi percorsi come

resources :devices
    
risposta data 15.06.2014 - 16:06
fonte

Leggi altre domande sui tag