我的问题是:在编辑个人资料页面时,如何让我的个人资料控制器的编辑/更新方法停止创建新记录?
我有一个用户模型和个人资料模型
user has_one :profile
。
profile belongs_to :user
。
我的routes.rb如下所示:map.resources:users,:has_one => :简档
当我的应用的访问者创建用户并点击提交时,他们会被定向到“创建个人资料”屏幕。
以下控制器创建一个配置文件,使创建的配置文件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
一切正常。
编辑个人资料时出现问题。
起初看起来很好。当我转到“编辑个人资料”视图时,网址是正确的。例如,如果“显示配置文件”视图的网址是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。
我认为问题来自(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 %>
答案 0 :(得分:7)
您需要传递嵌套属性的ID才能使更新操作正常运行。 如果您没有传递(允许)嵌套对象的id,rails将创建一个新记录。
答案 1 :(得分:2)
在编辑/更新中尝试此操作:
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的任何片段。
答案 2 :(得分:1)
form_for :profile, @profile, :html => { :method => :put } do |f|
您需要确保使用put方法来触发更新。
答案 3 :(得分:0)
可能的原因可能是您没有在请求的参数中传递配置文件的ID。
如果Rails找不到行,则会创建一个新行。
答案 4 :(得分:0)
试试这个:
@profile = current_user.profile.find_by_id(params[:id])