I followed this devise wiki documentation on how to write a custom update action for the registration controller when you want to allow users to edit their account without providing their passwords except if changing their passwords themselves. Devise Wiki - How to Allow Users to Edit Account Without Providing a Password.
However, I can't figure out what's missing in my Rspec test to make it pass. Here are the relevant code snippets:
app/controllers/registrations_controller.rb
def update
@user = User.find(current_user.id)
successfully_updated = if needs_password?(@user, params)
@user.update_with_password(devise_parameter_sanitizer.sanitize(:account_update))
else
# remove the virtual current_password attribute
# update_without_password doesn't know how to ignore it
params[:user].delete(:current_password)
@user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
end
if successfully_updated
set_flash_message :notice, :updated
# Sign in the user bypassing validation in case their password changed
sign_in @user, :bypass => true
redirect_to users_path
else
render "edit"
end
end
spec/factories/users.rb
FactoryGirl.define do
factory :user do
email { Faker::Internet.email }
password 'XXXXXXXXX'
first_name { Faker::Name.first_name }
middle_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
end
end
spec/controllers/registrations_controller_spec.rb
describe "PUT #update" do
login_pcp
let(:user) { FactoryGirl.create(:user, first_name: 'Tom') }
it "changes user attributes" do
attrs = FactoryGirl.attributes_for(:user, first_name: 'Jerry')
attrs.delete(:password)
put :update, user: attrs
user.reload
assigns[:user].should_not be_new_record
expect(user.first_name).to eq 'Jerry'
expect(flash[:notice]).to eq 'You updated your account successfully.'
end
end
When I run the spec I get the following error:
Failures:
1) RegistrationsController PUT #update changes user attributes
Failure/Error: expect(user.first_name).to eq 'Jerry'
expected: "Jerry"
got: "Tom"
(compared using ==)
# ./spec/controllers/registrations_controller_spec.rb:55:in `block (3 levels) in <top (required)>'
For some reason, it's not saving the update. I'm not sure if a password should be entered in order for the update to take place? Any help would be appreciated. Thanks!
The test now looks like this and it passes:
describe "PUT #update" do
before :each do
@request.env['devise.mapping'] = Devise.mappings[:user]
user_tom = FactoryGirl.create(:user, email: '[email protected]')
sign_in user_tom
end
it "changes user attributes" do
put :update, user: { email: '[email protected]' }
subject.current_user.reload
assigns[:user].should_not be_new_record
expect(subject.current_user.email).to eq '[email protected]'
expect(flash[:notice]).to eq 'You updated your account successfully.'
end
end