Метод редактирования создает новые записи, а не просто обновляет существующие - PullRequest
4 голосов
/ 29 августа 2009

Мой вопрос: как мне сделать так, чтобы методы редактирования / обновления моего контроллера профилей перестали создавать новые записи при редактировании страницы профиля?

У меня есть модель пользователя и модель профиля.
user has_one :profile.
profile belongs_to :user.

Мой route.rb выглядит так: map.resources: users,: has_one =>: profile

Когда посетитель моего приложения создает пользователя и нажимает кнопку "Отправить", он направляется на экран "Создать профиль".

Следующий контроллер создает профиль таким образом, чтобы URL создаваемого профиля был: 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] = 'Profile was successfully created.'
    redirect_to user_profile_path
  else
    flash[:notice] = 'Error.  Something went wrong.'
    render "new"
  end
end

Это все отлично работает.

Проблема возникает при редактировании профиля.

Сначала все выглядит хорошо. Когда я перехожу к представлению «изменить профиль», URL-адрес правильный. Например, если URL-адрес для представления «Показать профиль» - это localhost: 3000 / users / 1 / profile, то представление «Изменить профиль» выглядит так: localhost: 3000 / users / 1 / profile / edit

Это хорошо.

Когда я делаю изменения и нажимаю кнопку обновления, это, похоже, тоже работает. Меня направляют в правильный вид «Показать профиль», и я получаю флэш-уведомление, подтверждающее изменение.

Так вот странная часть. Когда я возвращаюсь к своему индексу профилей, чтобы просмотреть все профили в приложении, оказывается, что приложение создает новую запись профиля каждый раз, когда я обновляю профиль. Исходная запись профиля все еще там, но есть новые дополнительные записи. Помните, что все профили в моем приложении привязаны к пользователю, и у пользователя может быть только один профиль. Таким образом, если в моем приложении 5 пользователей, то теперь может быть 10 разных профилей, каждый с URL-адресом, который ведет к перенаправленной странице, поскольку user_id не существует в базе данных. Например, localhost: 3000 / users / 7 / profile, users / 8 / profile и т. Д.

Запись сохраняется в таблице профиля в моей базе данных, но в столбце user_id отображается NUL.

Я полагаю, что проблема связана с (а) методами редактирования / обновления в контроллере профилей или (б) кодом, который я использую для отображения профилей на странице индекса моего профиля.

Вот мой контроллер профиля для методов редактирования и обновления:

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] = 'Profile was successfully updated.'
    redirect_to(@profile)
  else
    render "edit"
  end

конец

Вот файл профиля index.html.erb:

<div id="posts">
  <% @profiles.each do |profile| -%>
    <% unless profile.blank? -%>
    <div class="profiles">
    <div class="right">
            <p><%=h profile.name %></p>
        <p><%=h profile.category %></p>
            </div>
    <div class="bottom">
            <p><%= link_to 'See Profile', user_profile_path(profile) %></p>
            </div>
    <% end -%>
</div>
<% end -%>

Чтобы повторить мой вопрос: как мне сделать так, чтобы методы редактирования / обновления контроллера моего профиля перестали создавать новые записи при редактировании страницы профиля?

UPDATE

Глядя на журнал, похоже, что он вызывает метод Edit, но затем вызывает метод "create" вместо метода "update" для выполнения действия. Вот что я получаю:

Processing ProfilesController#edit (for IP at 2009-08-29 00:46:06) [GET]  
  Parameters: {"action"=>"edit", "controller"=>"profiles", "user_id"=>"1"}  
  User Load (0.3ms)   SELECT * FROM "users" WHERE ("users"."id" = 1)   
  Profile Load (0.6ms)   SELECT * FROM "profiles" WHERE ("profiles".user_id = 1) LIMIT 1  
Rendering template within layouts/application  
Rendering profiles/edit  
  SQL (0.3ms)   SELECT count(*) AS count_all FROM "posts" WHERE ("posts".profile_id = 20)   
Rendered users/_login (1.2ms)  
Completed in 29ms (View: 16, DB: 1) | 200 OK 

[http://localhost/users/1/profile/edit]

Processing ProfilesController#create (for IP at 2009-08-29 00:46:21) [POST]  
  Parameters: {"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"}  
  User Load (0.3ms)   SELECT * FROM "users" WHERE ("users"."id" = 1)   
  Profile Load (0.6ms)   SELECT * FROM "profiles" WHERE ("profiles".user_id = 1) LIMIT 1  
  Profile Update (0.6ms)   UPDATE "profiles" SET "updated_at" = '2009-08-29 04:46:21', "user_id" = NULL WHERE "id" = 20  
  Profile Create (0.6ms)   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')  
Redirected to http://localhost:3000/users/1/profile  
Completed in 45ms (DB: 2) | 302 Found [http://localhost/users/1/profile]  

ОБНОВЛЕНИЕ

Я думаю, что это важная часть, но дайте мне знать, если вам нужно больше. Остальные только отдельные поля.

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

Ответы [ 5 ]

7 голосов
/ 15 января 2014

Вам нужно передать идентификатор вложенного атрибута, чтобы действие обновления работало хорошо. Если вы не передали (разрешенный) идентификатор вложенного объекта, rails создаст новую запись.

2 голосов
/ 29 августа 2009

Попробуйте это в вашем редактировании / обновлении:

def edit
  @profile = current_user.profile
end

def update
  @profile = current_user.profile
  if @profile.update_attributes(params[:profile])
    flash[:notice] = 'Profile was successfully updated.'
    redirect_to(@profile)
  else
    render "edit"
  end
end

В режиме редактирования попробуйте эту форму:

form_for @profile do |profile_form|

Если это не работает, тег post form, который генерирует rails, а также любые фрагменты вашего rout.rb, которые ссылаются на профили.

1 голос
/ 29 августа 2009
form_for :profile, @profile, :html => { :method => :put } do |f|

Вы должны убедиться, что используете метод put для запуска обновления.

0 голосов
/ 09 августа 2013

Попробуйте это:

@profile = current_user.profile.find_by_id(params[:id])
0 голосов
/ 26 июня 2013

Одной из возможных причин этого может быть то, что вы не передаете идентификатор профиля в параметрах запроса.

Если Rails не может найти строку, он создает новую.

...