2013-06-23 2 views
0

В моем приложении Rails У меня есть это обновление действия:Как проверить действие обновления с помощью RSpec?

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: "[email protected]") 
    put :update, id: @user, user: attributes_for(:user, email: "[email protected]") 
    @user.reload 
    expect(@user.new_email).to eq("[email protected]") 
end 

я получаю то же сообщение об ошибке:

1) UsersController user access PUT #update with valid attributes changes @user's new_email Failure/Error: expect(@user.new_email).to eq("[email protected]")

expected: "[email protected]" 
     got: nil 

    (compared using ==) 

Может ли кто-нибудь сказать мне, что мне здесь не хватает?

Спасибо за помощь!

+0

, которые являются ваши пользовательские поля в БД? – juanpastas

+0

'email',' new_email' и другие – Tintin81

ответ

0

Я думаю, что у вас есть опечатка

expect(@user.email).to eq("[email protected]") 

Вы не спасаем пользователя в 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 

Но есть больше изменений, чем это, это просто схема.

В любом случае, возможно, вы должны использовать обратный вызов в своей модели вместо того, чтобы писать больше кода в своем контроллере.

+0

Нет, это не опечатка. Цель состоит в том, чтобы сохранить в поле базы данных 'new_email'.Затем пользователь должен будет * подтвердить * свой новый адрес электронной почты по ссылке. – Tintin81

+0

Вы не сохраняете запись, позвольте мне изменить. – juanpastas

+0

Нет, 'save' тоже ничего не меняет. «New_email» сохраняется в базе данных (я вижу его там), но мой тест все равно не пройдет. Может быть, я ошибаюсь здесь. Я просто хочу, чтобы пользователи должны были подтвердить свой адрес электронной почты, если они когда-либо меняют его. Как бы выглядел такой «обратный вызов»? В идеале это должно срабатывать только при «обновлении». – Tintin81

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 
+0

Спасибо за вашу помощь и извините за то, что я не понял этого в своем первоначальном Я обновил выше, как мой '@ user' определен. Мое намерение состояло в том, чтобы просто сохранить код. – Tintin81