2009-03-02 9 views
4

Mein Benutzermodell hat den üblichen Primärschlüssel id, aber es hat auch einen eindeutigen login, der als ein Bezeichner verwendet werden kann. Daher möchte ich Routen definieren, so dass Benutzer entweder per ID oder per Login erreicht werden können. Im Idealfall würden die Routen in etwa so aussehen:Wie definiere ich RESTful-Routen in Rails für eine Ressource mit mehreren Schlüsselfeldern?

/users/:id (GET) => show (:id) 
/users/:id (PUT) => update (:id) 
... 

/users/login/:login (GET) => show (:login) 
/users/login/:login (PUT) => update (:login) 
... 

Was ist der beste Weg, dies (oder etwas ähnliches) zu tun?

Antwort

0

Nicht genau, was Sie hier tun, aber das kann eine Hilfe sein.

Sie können Aktionen definieren, die außerhalb der von Rails bereitgestellten automatischen RESTful-Routen liegen, indem Sie eine Option :member or :collection hinzufügen.

map.resources :users, :member => { :login => [:post, :get] } 

Dies Routen erzeugen, die wie folgt aussehen:

/users/:id (GET) 
... 
/users/:id/login (GET) 
/users/:id/login (POST) 

Eine andere Sache, die Sie gerade das Login als Attribut verwenden tun könnte, die man nach oben schaut (unter der Annahme, dass es einzigartig ist). Schauen Sie sich Ryan Bates screencast darauf an. In Ihrem Controller würden Sie haben:

def show 
@user = User.find_by_login(params[:id]) 
... 
end 

Er hat auch eine andere screencast die Ihnen helfen können. Die zweite spricht über benutzerdefinierte benannte Routen.

+0

Hallo vrish88, vielen Dank für Ihre Antwort. Es tut mir leid, dass meine Frage nicht klar genug war. Ich habe es gerade bearbeitet, um es klarer zu machen (hoffe ich). Ich habe in der Zwischenzeit eine mögliche Lösung gefunden (siehe unten). Es ist nicht großartig, also hoffe ich, dass jemand einen besseren Weg kennt. – MiniQuark

1

Bisher das Beste was ich tun konnte, ist dies:

map.resources :users 

map.resources :users_by_login, 
    :controller => "User", 
    :only => [:show, :edit, :update, :destroy], 
    :requirements => {:by_login => true} 

Die üblichen RESTful Routen sind für Anwender erstellt, und obendrein, die users_by_login Ressource fügt die folgenden Strecken (und nur diejenigen,):

GET /users_by_login/:id/edit 
GET /users_by_login/:id/edit.:format 
GET /users_by_login/:id 
GET /users_by_login/:id.:format 
PUT /users_by_login/:id 
PUT /users_by_login/:id.:format 
DELETE /users_by_login/:id 
DELETE /users_by_login/:id.:format 

Diese Routen tatsächlich auf die UserController auch abgebildet (für die show/edit/update/destroy Methoden nur). Ein zusätzlicher by_login Parameter wird hinzugefügt (gleich true): Auf diese Weise können die UserController Methoden feststellen, ob der Parameter id einen Login oder eine ID darstellt.

Es macht den Job, aber ich wünschte, es gäbe einen besseren Weg.

1

Überprüfen Sie, ob die an die Controller-Methoden übergebene ID eine Ganzzahl ist.

if params[:id].is_a?(Integer) 
    @user = User.find params[:id] 
else 
    @user = User.find_by_login params[:id] 

Keine Notwendigkeit, spezielle Routen hinzuzufügen.

+0

Ich dachte darüber nach, aber leider haben wir Benutzer, deren Login eine ganze Zahl ist! – MiniQuark

1

Eigentlich hat Kyle Boon hier die richtige Idee. Aber es ist etwas abseits. Wenn die Variable params eintrifft, werden alle Werte als Strings gespeichert, sodass das Beispiel jedes Mal false zurückgibt. Was können Sie tun, ist dies:

if params[:id].to_i.zero? 
@user = User.find_by_login params[:id] 
else 
@user = User.find params[:id] 
end 

diese Weise, wenn die: id eine tatsächliche Zeichenfolge Ruby wandelt es nur auf 0. Sie dies aus, indem man die params-Hash-Test können die ruby-debug gem verwenden.

(Ich habe gerade bemerkt haben würde, aber ich habe nicht genug Erfahrung, dass noch zu tun;)

+0

Nun leider haben wir einige Benutzer, deren Login eine ganze Zahl ist. Vielleicht kann ich es auf die eine oder andere Weise voranstellen. Ich werde es prüfen. – MiniQuark

+1

Was ist mit: @user = User.find (: erste,: Bedingungen => ['Login =? Oder ID =?', Params [: ID], Params [: ID]]) – vrish88

+0

@ vrish88 wenn Login und ID überlappen , in Ihrem Beispiel würde die ID eines Benutzers Sie zum Login eines anderen Benutzers bringen. –