2010-05-14 6 views
40

Mit Ruby on Rails 3 der neuen Routing-System ist es möglich, den Standard zu ändern: id ParameterÄndern der Parameter id in Rails Routing

resources :users, :key => :username 

kommen mit den folgenden Strecken

/users/new 
/users/:username 
/users/:username/edit 
...etc 

I Ich frage, denn obwohl das obige Beispiel einfach ist, wäre es in einem aktuellen Projekt, an dem ich gerade arbeite, sehr hilfreich.

Ist es möglich, diesen Parameter zu ändern, und wenn nicht, gibt es einen bestimmten Grund, warum nicht?

+3

Ich mag diese Frage aus der Perspektive von "Wie ändere ich die Standard-ID zum Abrufen eines Benutzers/Objekts/etc.?" Ich möchte jedoch nur ein Plug-In einfügen, um diese Standard-ID zu verschleiern, da es sich eher um einen Primärschlüssel handelt, und es gibt alle möglichen Sicherheitsgründe, warum Sie diesen Wert nicht verfügbar machen sollten (Lockerung von SQL-Injection-Angriffen, ratenbare IDs) für andere Benutzer, ...). Insbesondere ermöglicht die Verwendung des Benutzernamens den direkten Angriff auf ein Konto (pwd rate). Ein großer zufälliger und einzigartiger Wert macht all das viel schwieriger. Prost. –

+0

* Achten Sie darauf, die Antworten nach dem akzeptierten zu lesen * – blnc

Antwort

34

Wenn ich Sie richtig verstehe, was Sie wollen, ist die username anstelle von id in Ihrer URL, richtig?

Sie können dies tun, indem Sie die Methode to_param in Ihrem Modell überschreiben. Sie können weitere Informationen here erhalten.

+0

Ich denke, das ist der einzige Weg, um es für jetzt zu tun. Scheint irgendwie ein bisschen Kreisverkehr. – joeellis

+1

Danke für diesen Zeiger, löste mein Problem vollständig. Ich bin hier hergekommen, um zu schauen, wie man diesen b/c ändert, nach Richtlinien betrachten wir das Abrufen per Primärschlüssel-ID aus dem Internet als Sicherheitsproblem. Stattdessen fügen wir dem Objekt einen großen zufälligen und eindeutigen Wert hinzu (SecureRandom.urlsafe_base64 (15)) und verwenden dies als die ID, die von to_param zurückgegeben wird, und wenn die RESTful-APIs find_by_OID verwenden. Vielleicht, wenn ich Ruby/Rails besser verstehe, kann dies zu einem Juwel gemacht werden. –

0

Übergeben Sie den Benutzernamen als Eingabe für die Pfadhelfer.

Ihrer Ansicht Code:

user_path(u.username) #/users/john 

In Ihrem Controller behandeln die id erhielt als username:

def show 
    user = User.find_by_username!(params[:id]) 
    ... 
end 
+0

Das ist etwas, was ich gemacht habe, aber ich denke, es wäre einfacher, etwas wie User.find_by_username (params [: username]) im Code zu machen. Ich frage mich wirklich, warum Rails das generell nicht erlaubt. Ist es vielleicht gegen irgendein REST-Prinzip? – joeellis

1

Obwohl die Antwort durch den Fragesteller akzeptiert worden, aber es ist ein einfacher Ansatz mach das. Schreiben Sie diesen Code in Ihren Controller.

und in Ihrer Sicht, wo Sie den Link anzeigen möchten, schreiben Sie diesen Code.

<%= link_to "Username", user_path(u.username) %> 

Sie brauchen keine weiteren Änderungen an Ihren Routen oder Controller.

UPDATE: Dies funktioniert nur, wenn Sie CanCan gem.

+0

Das scheint eine CanCan-Methode zu sein. Es ist überhaupt nicht in den Schienen api erwähnt. [apidock.com] (http://apidock.com/rails/search?query=authorize_resource) [api.rubyonrails.org] (http://api.rubyonrails.org/?q=authorize_resource) – Nultyi

+0

Ja, das ist eine CanCan-Methode. Ich habe vergessen, das in meiner Antwort zu erwähnen. Ich habe die Antwort aktualisiert. – KULKING

61

In Ihrer Route können Sie

resources :user, param: :username 
+4

Dies sollte die akzeptierte Antwort sein, ich bin viel bequemer hinzufügen ein Argument zu einer Route als ich überschreiben die 'to_param' Methode – omnikron

+1

@omnikron es hängt davon ab, was Sie versuchen, in Ihrer App zu erreichen, manchmal müssen Sie beides tun (zB wenn Sie Ihre Ressource direkt an die Routing-Helfer 'user_path @ user' übergeben möchten, so dass Sie' user_path @ user.username' nicht tun müssen) ... aber ja, Sie haben Recht, das ist elegant, wenn Sie es einfach tun möchte Routing-Funktionalität. – equivalent8

+3

Dies funktioniert nur auf Rails 4+ –

23

für Ruby on Rails 4.1 verwenden.4 (und möglicherweise auch frühere Versionen) Sie müssen tun, was beidej.. und Ujjwal vorgeschlagen:

1) In config/routes.rb hinzufügen:

resources :user, param: :username 

2) In app/models/user.rb hinzufügen:

def to_param 
    username 
end 

In nur tun # 1 dann werden alle Ihre Routen korrekt sein, wie von rake routes zu sehen ist:

$ rake routes 
    Prefix Verb URI Pattern     Controller#Action 
user_index GET /user(.:format)    user#index 
      POST /user(.:format)    user#create 
    new_user GET /user/new(.:format)   user#new 
edit_user GET /user/:username/edit(.:format) user#edit 
     user GET /user/:username(.:format)  user#show 
      PATCH /user/:username(.:format)  user#update 
      PUT /user/:username(.:format)  user#update 
      DELETE /user/:username(.:format)  user#destroy 

Jedoch enthalten die Hilfsmethoden, die eine URL basierend auf einer User Instanz erstellen, immer noch die id in der URL, z. /user/1. Um die username in den konstruierten URLs zu erhalten, müssen Sie to_param wie in # 2 überschreiben.

+4

die 2) wird die meiste Zeit verpasst, wenn diese Frage erscheint; dies sollte die akzeptierte Antwort sein – Ben

+0

** arbeitet mit ** 'rails 5.0.2' ** und **' ruby ​​2.4.1' – blnc