在我的Rails应用程序中,我有更新操作:
class UsersController < ApplicationController
before_filter :authorized_user
def update
current_email = @user.email
new_email = params[:user][:email].downcase.to_s
if @user.update_attributes(params[:user])
if new_email != current_email
@user.change_email(current_email, new_email)
flash[:success] = "Please click on the link that we've sent you."
else
flash[:success] = "User updated."
end
redirect_to edit_user_path(@user)
else
render :edit
end
end
private
def authorized_user
@user = User.find(params[:id])
redirect_to(root_path) unless current_user?(@user)
end
end
class User < ActiveRecord::Base
def change_email(old_email, new_email)
self.email = old_email
self.new_email = new_email.downcase
self.send_email_confirmation_link
end
end
现在,当我在浏览器中手动测试更新操作时,一切正常。
我写的 RSpec 测试不起作用,我无法弄清楚原因:
it "changes @user's new_email" do
@user = create(:user, email: "john@doe.com")
put :update, id: @user, user: attributes_for(:user, email: "new@email.com")
@user.reload
expect(@user.new_email).to eq("new@email.com")
end
我一直收到同样的错误消息:
1)UsersController用户访问PUT #update,有效属性更改@ user的new_email 失败/错误:期待(@ user.new_email).to eq(“new@email.com”)
expected: "new@email.com"
got: nil
(compared using ==)
有人可以告诉我这里缺少什么吗?
感谢您的帮助!
答案 0 :(得分:0)
我认为你有一个错字
expect(@user.email).to eq("new@email.com")
您没有在change_email
中保存用户,并且您正在更新控制器中的email
。因此,代码中未更新new_email
。
要保存记录,请使用
def change_email(old_email, new_email)
self.email = old_email
self.new_email = new_email.downcase
save
self.send_email_confirmation_link
end
可能是这样的:
# controller
if @user.update_attributes[:user]
redirect_to somewhere
else
render :edit
# model
after_update :change_email
但是有更多的变化,这只是一个模式。
无论如何,也许您应该在模型中使用回调,而不是在控制器中编写更多代码。
答案 1 :(得分:0)
您的控制器存在一些问题。
首先,您尚未定义@user
。这就是你的结果为零的原因
# Define it
@user = User.find(params[:id]) # if your url is POST /user/1/update
其次,最好不要仅使用email
,如果您希望允许用户进一步编辑其他属性,请说生日等等?
第三,更新用户属性比其他人有点棘手,用户必须有权这样做。考虑到一个用户在浏览器中操作表单属性并发布给另一个用户update
,会发生什么?
因此,您必须检查用户是否可以这样做。
结合在一起:
def update
@user = User.find(params[:id])
if @user != current_user
return redirect_to(:back, alert: "not allowed to edit")
end
attrs = params[:user]
if @user.update_attributes attrs
//do something
else
render { action 'edit' }
end
end