0

在我的 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 失败/错误:expect(@user.new_email).to eq("new@email.com")

   expected: "new@email.com"
        got: nil

   (compared using ==)

谁能告诉我我在这里想念什么?

谢谢你的帮助!

4

2 回答 2

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

但是还有比这些更多的变化,这只是一个模式。

无论如何,也许您应该在模型中使用回调,而不是在控制器中编写更多代码。

于 2013-06-23T17:10:05.477 回答
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
于 2013-06-23T18:15:08.803 回答