2013-10-11 64 views
0

我真的很苦惱與Rspec DSL!我在互聯網上閱讀了很多,所以我發佈了我的特殊問題,因爲我的軟弱頭腦無法獲得解決方案。控制器規格拋出未定義的方法

在我的控制器中有一個post方法來更新用戶的電子郵件。工作正常,但我正在努力與規範,因爲我所得到的是NilClass的未定義方法(即使我已經試圖存儲每個對象和方法等)。

users_controller.rb

def update_user_email 
    @user = User.find_by_id(params[:id]) 
    new_email = params[:user][:new_email].downcase.strip 
    user_check = User.find_by_email('new_email') 
    if user_check.blank? 
    @user.email = new_email 
    @user.save 
    flash[:notice] = "Email updated to #{new_email}" 
    else 
    flash[:alert] = "This email is already being used by someone else!" 
    end 

    respond_with @user do |format| 
    format.html { redirect_to admin_user_path(@user) } 
    format.json { head :no_content } 
    end 
end 

這是我想寫的規範。我應該寫什麼測試,如果不是這樣,我該怎麼做才能防止對NilClass錯誤的未定義方法!

users_controller_spec.rb

describe Admin::UsersController do 
    let!(:user) { FactoryGirl.create(:user, password: 'oldpass', email: '[email protected]') } 
    ... 
    describe "admin actions for each user" do 
    it "resets user email" do 
     post :update_user_email, {user: {new_email: '[email protected]'} } 
     response.status.should == 200 
    end 
    end 
... 
end 

和錯誤:

Admin::UsersController admin actions for each user resets user email 
Failure/Error: post :update_user_email, {user: {new_email: '[email protected]'} } 
NoMethodError: 
    undefined method `email=' for nil:NilClass 

回答

1

發生故障的線路是:

@user = User.find_by_id(params[:id) 

既然你是不是在測試期間傳遞的ID在用戶不被發現,因此,您要撥打電子郵件=上爲零。這裏是你如何清理你的控制器和測試。

class YourController < ApplicationController 
    before_filter :find_user, only: [:update_user_email] 

    def update_user_email 
    new_email = params[:user][:new_email].downcase.strip 
    user_check = User.where(email: new_email) 
    if user_check.blank? 
     @user.email = new_email 
     @user.save 
     flash[:notice] = "Email updated to #{new_email}" 
    else 
     flash[:alert] = "This email is already being used by someone else!" 
    end 

    respond_with @user do |format| 
     format.html { redirect_to admin_user_path(@user) } 
     format.json { head :no_content } 
    end 
    end 

    def find_user 
    @user = User.find(params[:id]) 
    rescue ActiveRecord::RecordNotFound 
     flash[:error] = "It looks like that user does not exist" 
     # redirect or render 
    end 
end 


# your test 


describe "admin actions for each user" do 
    it "resets user email" do 
    post :update_user_email, id: user.id, user: {new_email: '[email protected]'} 
    response.status.should == 200 
    end 
end 

您可能還想考慮將邏輯移出控制器並進入服務對象。該控制器方法正在變得有點長。

0

在你post :update_user_email你不及格:ID ...所以@user = User.find_by_id...沒有找到用戶,以便@user是nil對象。

post :update_user_email, id: user.id, {user: {new_email: '[email protected]'} } 
1

問題是您還需要傳遞您想要更新的User的ID。由於@user爲零,故障線路爲@user.email = new_email

爲了讓您的測試現在通過,你需要改變你的post方法:

post :update_user_email, {id:'[email protected]', user: {new_email: '[email protected]'} } 

順便說一句,可以說,它可能是更好的爲你實際上是在做這在UsersController#update方法中,以維護RESTful路由。至於執行唯一的電子郵件地址 - 最好在User類中進行驗證。

相關問題