编辑方法是创建新记录,而不仅仅是更新现有记录 [英] Edit method is creating new records, instead of just updating existing ones

查看:22
本文介绍了编辑方法是创建新记录,而不仅仅是更新现有记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是:当我编辑个人资料页面时,如何使我的个人资料控制器的编辑/更新方法停止创建新记录?

我有一个用户模型和配置文件模型.
user has_one :profile.
profile属于_to :user.

我的 routes.rb 看起来像这样:map.resources :users, :has_one => :profile

当我的应用的访问者创建用户并点击提交时,他们会被定向到创建个人资料"屏幕.

以下控制器创建一个配置文件,使创建的配置文件 url 为:localhost:3000/users/[user_id]/profile

def new@profile = `current_user.build_profile`结尾定义创建@profile = current_user.build_profile(params[:profile])如果@profile.saveflash[:notice] = '配置文件已成功创建.'重定向到 user_profile_path别的flash[:notice] = '错误.出问题了.'呈现新"结尾结尾

这一切正常.

当我编辑配置文件时出现问题.

乍一看还不错.当我转到编辑个人资料"视图时,网址是正确的.例如,如果show profile"视图的 url 是 localhost:3000/users/1/profile,那么edit profile"视图显示为:localhost:3000/users/1/profile/edit

那很好.

当我进行更改并单击更新按钮时,这似乎也有效.我被定向到正确的显示个人资料"视图,并收到一条确认更改的快速通知.

所以这是奇怪的部分.当我返回我的个人资料索引以查看应用程序中的所有个人资料时,结果发现每次我更新个人资料时,该应用程序都会创建一个新的个人资料记录.原始配置文件记录仍然存在,但有新的附加记录.请记住,我的应用程序中的所有配置文件都与一个用户相关联,并且该用户只能拥有一个配置文件.因此,如果我的应用程序中有 5 个用户,那么现在可能有 10 个不同的配置文件,每个配置文件的 url 都指向一个被破坏的页面,因为数据库中不存在 user_id.例如localhost:3000/users/7/profile、users/8/profile等

记录已保存到我数据库中的配置文件表中,但 user_id 列显示为 NUL.

我认为问题来自 (a) 配置文件控制器中的编辑/更新方法,或 (b) 我用来在我的配置文件索引页面上显示配置文件的代码.

这是我用于编辑和更新方法的配置文件控制器:

def 编辑@profile = current_user.profile(params[:id])结尾定义更新@profile = current_user.profile.find(params[:id])如果@profile.update_attributes(params[:profile])flash[:notice] = '配置文件已成功更新.'重定向到(@profile)别的渲染编辑"结尾

结束

这是配置文件 index.html.erb 视图文件:

<% @profiles.each 做 |profile|-%><% 除非 profile.blank?-%><div class="profiles"><div class="right"><p><%=h profile.name%</p><p><%=h profile.category%</p>

<div class="bottom"><p><%= link_to '查看个人资料', user_profile_path(profile) %></p>

<%结束-%>

<%结束-%>

重复我的问题:当我编辑个人资料页面时,如何让我的个人资料控制器的编辑/更新方法停止创建新记录?

更新

看日志,好像是在调用Edit方法,然后调用了create"方法而不是update"方法来执行动作.这是我得到的:

Processing ProfilesController#edit (for IP at 2009-08-29 00:46:06) [GET]参数:{"action"=>"edit", "controller"=>"profiles", "user_id"=>"1"}用户负载 (0.3ms) SELECT * FROM "users" WHERE ("users"."id" = 1)Profile Load (0.6ms) SELECT * FROM "profiles" WHERE ("profiles".user_id = 1) LIMIT 1布局/应用程序中的渲染模板渲染配置文件/编辑SQL (0.3ms) SELECT count(*) AS count_all FROM "posts" WHERE ("posts".profile_id = 20)呈现的用户/_login (1.2ms)在 29 毫秒内完成(视图:16,DB:1)|200 正常

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

Processing ProfilesController#create (for IP at 2009-08-29 00:46:21) [POST]参数:{"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"}用户负载 (0.3ms) SELECT * FROM "users" WHERE ("users"."id" = 1)Profile Load (0.6ms) SELECT * FROM "profiles" WHERE ("profiles".user_id = 1) LIMIT 1Profile Update (0.6ms) UPDATE "profiles" SET "updated_at" = '2009-08-29 04:46:21', "user_id" = NULL WHERE "id" = 20配置文件创建 (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', '地方很棒.', NULL, '555-1212', 1, 'NY', '地方@whatever.com', '2009-08-29 04:46:21')重定向到 http://localhost:3000/users/1/profile45ms 内完成 (DB: 2) |302 发现 [http://localhost/users/1/profile]

更新

我认为这是相关部分,但如果您需要更多,请告诉我.其余的只是个别字段.

<% @profile.posts.build 如果@profile.posts.empty?%><% form_for :profile, @profile, :url =>{:控制器=>'个人资料', :action =>'更新' } 做 |profile_form|%><%= profile_form.error_messages %>

解决方案

您需要传递嵌套属性的 ID 才能使更新操作正常工作.如果您没有传递(允许)嵌套对象的 id,rails 将创建一个新记录.

My question is: How do I make the edit/update methods for my profiles controller stop creating new records when I edit a profile page?

I have a user model and profile model.
user has_one :profile.
profile belongs_to :user.

My routes.rb looks like this: map.resources :users, :has_one => :profile

When a visitor to my app creates a user and hits submit, they are directed to the "create profile" screen.

The following controller, creates a profile such that the created profile url is: 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

This all works fine.

The problem occurs when I edit a profile.

At first things seems fine. When I go to the "edit profile" view, the url is correct. For example, if the url for the "show profile" view is localhost:3000/users/1/profile, then the "edit profile" view appears as: localhost:3000/users/1/profile/edit

That's good.

When I make a change and click the update button, that seems to work as well. I get directed to the correct "show profile" view and I get a flash notice confirming the change.

So here's the weird part. When I go back to my index of profiles to view all the profiles in the app, it turns out that the app has created a new profile record each time I update the profile. The original profile record is still there, but there are new additional records. Keep in mind that all the profiles in my app are tied to a user, and the user can have only one profile. So if there are 5 users in my app, now there might be 10 different profiles, each with a url that leads to a busted page because the user_id doesn't exist in the database. For example, localhost:3000/users/7/profile, users/8/profile, etc.

The record gets saved to the profile table in my database, but the user_id column shows a NUL.

I figure that the problem is coming from either (a) the edit/update methods in the profiles controller, or (b) the code I'm using to display profiles on my profile index page.

Here's my profile controller for the edit and update methods:

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

end

Here's the profile index.html.erb view file:

<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 -%>

To repeat my question: How do I make the edit/update methods for my profiles controller stop creating new records when I edit a profile page?

UPDATE

Looking at the log, it looks like it's calling the Edit method, but then calling the "create" method instead of the "update" method to execute the action. Here's what I'm getting:

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]  

UPDATE

I think this is the relevant part, but let me know if you need more. The rest is just the individual fields.

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

解决方案

You need to pass an ID of the nested attribute to make update action work well. If you didn't pass(permitted) id of nested object, rails will create a new record.

这篇关于编辑方法是创建新记录,而不仅仅是更新现有记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆