[英]How to test my update action with RSpec?
In my Rails application I have this update action: 在我的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
Now, everything works perfectly when I test the update action manually in the browser. 现在,当我在浏览器中手动测试更新操作时,一切工作正常。
The RSpec test that I wrote, however, does not work and I can't figure out why: 但是,我编写的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
I keep getting the same error message: 我不断收到相同的错误消息:
1) UsersController user access PUT #update with valid attributes changes @user's new_email Failure/Error: expect(@user.new_email).to eq("new@email.com") 1)UsersController用户访问PUT #update具有有效属性会更改@user的new_email失败/错误:期望(@ user.new_email).to eq(“ new@email.com”)
expected: "new@email.com"
got: nil
(compared using ==)
Can anybody tell me what I am missing here? 有人可以告诉我我在这里想念什么吗?
Thanks for any help! 谢谢你的帮助!
I think you have a typo 我想你有错字
expect(@user.email).to eq("new@email.com")
You are not saving user in change_email
, and you are updating email
in your controller. 您不是将用户保存在change_email
,而是在控制器中更新email
。 So new_email
is not updated in your code. 因此, new_email
不会在您的代码中更新。
To save your record use 保存记录使用
def change_email(old_email, new_email)
self.email = old_email
self.new_email = new_email.downcase
save
self.send_email_confirmation_link
end
Could be something like this: 可能是这样的:
# controller
if @user.update_attributes[:user]
redirect_to somewhere
else
render :edit
# model
after_update :change_email
But there are more changes than these, this is just a schema. 但是变化不止这些,这仅仅是一个模式。
anyway, maybe you should use a callback in your model instead of writing more code in your controller. 无论如何,也许您应该在模型中使用回调,而不是在控制器中编写更多代码。
There are some problems in your controller. 控制器中存在一些问题。
Firstly, you have not defined @user
at all. 首先,您根本没有定义@user
。 That's the reason your result is nil 那就是你的结果为零的原因
# Define it
@user = User.find(params[:id]) # if your url is POST /user/1/update
Secondly, better not to use email
only, what if in the further you want to allow users to edit other attributes say birthday etc? 其次,最好不要只使用email
,如果还希望允许用户编辑其他属性(例如生日等)怎么办?
Thirdly, updating user attributes is a bit tricky than others, the user must have authority to do that. 第三,更新用户属性比其他属性有些棘手,用户必须有权这样做。 Considering one user manipulate the form attributes in browser and post to another user's update
, what will happen? 考虑到一个用户在浏览器中操纵表单属性并将其发布到另一用户的update
,将会发生什么?
So you must check if the user can do that. 因此,您必须检查用户是否可以这样做。
Combining together: 结合在一起:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.