4 Stimmen

Die Edit-Methode erstellt neue Datensätze anstatt nur vorhandene zu aktualisieren

Meine Frage lautet: Wie kann ich die Edit-/Update-Methoden für meinen Profil-Controller so ändern, dass keine neuen Datensätze erstellt werden, wenn ich eine Profilseite bearbeite?

Ich habe ein Benutzermodell und ein Profilmodell.
Benutzer hat ein Profil.
Profil gehört zu Benutzer.

Meine routes.rb sieht so aus: map.resources :users, :has_one => :profile

Wenn ein Besucher meiner App einen Benutzer erstellt und auf Senden klickt, wird er zur "Profil erstellen"-Seite weitergeleitet.

Der folgende Controller erstellt ein Profil, sodass die erstellte Profil-URL lautet: localhost:3000/users/[user_id]/profile

def new  
    @profile = `current_user.build_profile`  
end

def create
  @profile = current_user.build_profile(params[:profile])
  if @profile.save
    flash[:notice] = 'Profil wurde erfolgreich erstellt.'
    redirect_to user_profile_path
  else
    flash[:notice] = 'Fehler. Etwas ist schiefgelaufen.'
    render "new"
  end
end

Dies funktioniert alles gut.

Das Problem tritt auf, wenn ich ein Profil bearbeite.

Zunächst scheint alles in Ordnung zu sein. Wenn ich zur "Profil bearbeiten"-Ansicht gehe, ist die URL korrekt. Zum Beispiel, wenn die URL für die "Profil anzeigen"-Ansicht localhost:3000/users/1/profile ist, dann erscheint die "Profil bearbeiten"-Ansicht als: localhost:3000/users/1/profile/edit

Das ist gut.

Wenn ich eine Änderung vornehme und auf die Update-Schaltfläche klicke, scheint das auch zu funktionieren. Ich werde zur richtigen "Profil anzeigen"-Ansicht weitergeleitet und erhalte eine Blitzmeldung, die die Änderung bestätigt.

Hier kommt der seltsame Teil. Wenn ich zu meinem Profil-Index zurückkehre, um alle Profile in der App anzuzeigen, stellt sich heraus, dass die App jedes Mal, wenn ich ein Profil aktualisiere, einen neuen Profildatensatz erstellt. Der ursprüngliche Profildatensatz ist immer noch vorhanden, aber es gibt neue zusätzliche Datensätze. Bedenken Sie, dass alle Profile in meiner App mit einem Benutzer verbunden sind und der Benutzer nur ein Profil haben kann. Wenn es also 5 Benutzer in meiner App gibt, könnten jetzt 10 verschiedene Profile vorhanden sein, von denen jedes eine URL hat, die zu einer fehlerhaften Seite führt, weil die Benutzer-ID nicht in der Datenbank vorhanden ist. Zum Beispiel localhost:3000/users/7/profile, users/8/profile usw.

Der Datensatz wird in der Profiltabelle meiner Datenbank gespeichert, aber die user_id-Spalte zeigt ein NUL.

Ich gehe davon aus, dass das Problem entweder von (a) den Edit-/Update-Methoden im Profil-Controller oder (b) dem Code kommt, den ich verwende, um Profile auf meiner Profil-Indexseite anzuzeigen.

Hier ist mein Profil-Controller für die Edit- und Update-Methoden:

def edit
    @profile = current_user.profile(params[:id])
end

def update
  @profile = current_user.profile.find(params[:id])
  if @profile.update_attributes(params[:profile])
    flash[:notice] = 'Profil wurde erfolgreich aktualisiert.'
    redirect_to(@profile)
  else
    render "edit"
  end

Ende

Hier ist die Profil index.html.erb Ansichtsdatei:

Zur Wiederholung meiner Frage: Wie kann ich die Edit-/Update-Methoden für meinen Profil-Controller so ändern, dass keine neuen Datensätze erstellt werden, wenn ich eine Profilseite bearbeite?

UPDATE

Wenn ich mir das Protokoll anschaue, sieht es so aus, als würde es die Edit-Methode aufrufen, aber dann statt der "Update"-Methode die "create"-Methode aufrufen, um die Aktion auszuführen. Hier ist, was ich erhalte:

Verarbeiten von ProfilesController#edit (für IP um 2009-08-29 00:46:06) [GET]  
  Parameter: {"action"=>"edit", "controller"=>"profiles", "user_id"=>"1"}  
  Benutzer laden (0.3 ms)   SELECT * FROM "users" WHERE ("users"."id" = 1)   
  Profil laden (0.6 ms)   SELECT * FROM "profiles" WHERE ("profiles".user_id = 1) LIMIT 1  
Template innerhalb von layouts/application rendern  
Profiles/rendern/edit  
  SQL (0.3 ms)   SELECT count(*) AS count_all FROM "posts" WHERE ("posts".profile_id = 20)   
Benutzer/_login gerendert (1.2 ms)  
Abgeschlossen in 29 ms (Ansicht: 16, DB: 1) | 200 OK 

[[http://localhost/users/1/profile/edit\]](http://localhost/users/1/profile/edit])

Verarbeiten von ProfilesController#create (für IP um 2009-08-29 00:46:21) [POST]  
  Parameter: {"commit"=>"Update", "profile"=>{"city"=>"Brooklyn", "address1"=>"Bedford Ave.", "name"=>"Place", "zip"=>"19876", "address2"=>"Apt. 4", "category"=>"Restaurant", "website"=>"http://www.whatever.com", "description"=>"Place is awesome.", "phone"=>"555-1212", "email"=>"place@whatever.com", "state"=>"NY"}, "action"=>"create", "authenticity_token"=>"[redacted]", "controller"=>"profiles", "user_id"=>"1"}  
  Benutzer laden (0.3 ms)   SELECT * FROM "users" WHERE ("users"."id" = 1)   
  Profil laden (0.6 ms)   SELECT * FROM "profiles" WHERE ("profiles".user_id = 1) LIMIT 1  
  Profil aktualisieren (0.6 ms)   UPDATE "profiles" SET "updated_at" = '2009-08-29 04:46:21', "user_id" = NULL WHERE "id" = 20  
  Profil erstellen (0.6 ms)   INSERT INTO "profiles" ("name", "address1", "city", "address2", "zip", "category", "updated_at", "website", "description", "category_id", "phone", "user_id", "state", "email", "created_at") VALUES('Place', 'Bedford Ave.', 'Brooklyn', 'Apt. 4', '19876', 'Restaurant', '2009-08-29 04:46:21', 'http://www.whatever.com', 'Place is awesome.', NULL, '555-1212', 1, 'NY', 'place@whatever.com', '2009-08-29 04:46:21')  
Umgeleitet zu http://localhost:3000/users/1/profile  
Abgeschlossen in 45 ms (DB: 2) | 302 Found [http://localhost/users/1/profile]  

UPDATE

Ich denke, das ist der relevante Teil, aber lassen Sie mich wissen, wenn Sie mehr benötigen. Der Rest sind nur die einzelnen Felder.

<% @profile.posts.build if @profile.posts.empty? %>  
<% form_for :profile, @profile, :url => { :controller => 'profiles', :action => 'update' } do |profile_form| %>  
<%= profile_form.error_messages %>

7voto

Srle Punkte 10072

Sie müssen die ID des verschachtelten Attributs übergeben, damit die Aktualisierungsaktion korrekt funktioniert. Wenn Sie die (zugelassene) ID des verschachtelten Objekts nicht übergeben haben, wird Rails einen neuen Datensatz erstellen.

2voto

Andy Gaskell Punkte 30777

Versuchen Sie dies in Ihrem Bearbeitungs- / Aktualisierung:

def edit
  @profile = current_user.profile
end

def update
  @profile = current_user.profile
  if @profile.update_attributes(params[:profile])
    flash[:notice] = 'Profil wurde erfolgreich aktualisiert.'
    redirect_to(@profile)
  else
    render "edit"
  end
end

In Ihrer Bearbeitungsansicht verwenden Sie dieses form_for:

form_for @profile do |profile_form|

Wenn dies nicht funktioniert, posten Sie das Formular-Tag, das Rails generiert, sowie alle Ausschnitte Ihrer routes.rb, die Profile referenzieren.

1voto

nitecoder Punkte 5446
form_for :profile, @profile, :html => { :method => :put } do |f|

Sie müssen sicherstellen, dass Sie die put-Methode verwenden, um ein Update auszulösen.

0voto

ang3lkar Punkte 99

Ein möglicher Grund hierfür könnte sein, dass Sie die Profil-ID nicht in den Parametern der Anfrage übergeben.

Wenn Rails keine Zeile finden kann, erstellt es stattdessen eine neue.

0voto

bharath Punkte 623

Versuchen Sie es mit:

@profile = current_user.profile.find_by_id(params[:id])

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X