简体   繁体   English

如何使用RSpec测试我的更新操作?

[英]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

Callback 打回来

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM