【问题标题】:Edit method is creating new records, instead of just updating existing onesEdit 方法是创建新记录,而不是仅仅更新现有记录
【发布时间】:2010-11-23 22:27:44
【问题描述】:

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

我有一个用户模型和配置文件模型。
user has_one :profile.
profile belongs_to :user.

我的 routes.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

这一切都很好。

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

起初一切似乎都很好。当我转到“编辑个人资料”视图时,网址是正确的。例如,如果“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 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 -%>

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

更新

看日志,好像是在调用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 %>

【问题讨论】:

  • 请同时发布您的编辑视图代码。具体来说,我正在寻找表单代码。
  • 我应该解释一下。我正在向个人资料添加帖子,所以我认为编辑视图中的一些表单代码与此相关。我正在关注 Rails 网站上的入门指南。他们建议将“f”更改为“form”,我认为第一行代码也与此有关。但在我开始尝试添加帖子之前,我遇到了同样的问题。

标签: ruby-on-rails methods controller views


【解决方案1】:

在您的编辑/更新中试试这个:

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:

form_for @profile do |profile_form|

如果这不起作用,则发布 rails 生成的表单标签以及引用配置文件的 routes.rb 的任何 sn-ps。

【讨论】:

  • 没用。结果相同。但是请参阅上面我更新的 cmets,解释更多细节。
  • 我尝试了您的更新修复,但它引发了错误。 Rails 目前在 html 中生成的表单是:
    .
  • routes.rb 没有配置文件参考,除了:map.resources :users, :has_one => :profile
  • 我认为最大的问题是:应用程序如何跳转到“创建”方法?闪存通知显示仅与我的控制器中的“创建”方法相关联的确认消息。所以不知何故,当它显然应该从“编辑”方法转到“更新”方法时,我从“编辑”方法跳到“创建”方法。我就是不明白。
【解决方案2】:
form_for :profile, @profile, :html => { :method => :put } do |f|

您需要确保使用 put 方法来触发更新。

【讨论】:

  • 当我进行此更改时,提交更新会引发以下异常:ActionController::MethodNotAllowed(只允许获取请求。):
【解决方案3】:

造成这种情况的一个可能原因是您没有在请求的参数中传递配置文件的 ID。

如果 Rails 找不到行,它会创建一个新行。

【讨论】:

    【解决方案4】:

    试试这个:

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 2020-06-20
        • 2023-01-12
        • 2012-07-25
        • 2021-03-30
        • 2011-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多