I am trying to test a create action on my users controller. The ask is to allow customers who have previously created accounts, but never actually created a subscription, to use the same email at signup but not be bound to their original password. My test is as follows:
it "updates the user password for user with no entitlement" do
user6 = Factory(:user)
user_params_without_entitlement= { :email => user6.email, :password => "mynewpassword", :password_confirmation => "mynewpassword", publisher_id: user6.publisher_id }
post :create, user_params_without_entitlement
hash = Hashie::Mash.new(JSON.parse response.body)
expect(hash[:errors].present?).to eq(false)
expect(user6.password).to eq("mynewpassword")
end
my controller looks like:
def create
if @user.save && @user.activate!
render :create, status: 200
elsif @user.errors[:email].first == "Oops! Looks like you've already created an account. Please <a href='/account'>click here to sign in.</a>"
user = User.find_by_email(params[:email])
if user.user_entitlements.empty? && user.update_attributes(password: params[:password], password_confirmation: params[:password_confirmation])
render :create, status: 200
else
render json: {errors: @user.errors}, status: 422
end
else
if render json: {errors: @user.errors}, status: 422
end
end
end
If I put a binding in below the
user.user_entitlements.empty? && user.update_attributes(password: params[:password], password_confirmation: params[:password_confirmation])
and I call user.password I get "mynewpassword" so the password is updating. in the test though the password is still showing as the original password. I tried adding user6.reload! in the test before the expectation block and I get
NoMethodError: undefined method `reload!' for #<User:0x007fa9a3342fc0>
I found this issue: https://github.com/rweng/pry-rails/issues/9 which suggests that I should modify my .pryrc file. I didn't have a .pryrc file previously. I created a .pryrc file and tried everything in this post( pry gem how to reload? ) one at a time with no success. I created the .pryrc in the root of the app and at this point I am at a loss as to what to do.
it is object.reload
to reload an object - without the !bang inside the console you use reload!
to reload the hole application models.
so in your case do user6.reload
just to clearout for you, how to use object.reload correctly
User has one profile which has autosave. After_save of profile, the profile is calculating the age and writes that to the user.
[69] pry(main)> a = User.last
[70] pry(main)> a.age
=> 80
[71] pry(main)> a.profile.birthday = 18.years.ago
[72] pry(main)> a.save
......
SQL (0.3ms) UPDATE "users" SET "age" = 18 WHERE "users"."id" = $1 [["id", 6]]
....
[73] pry(main)> a.age
=> 80
[74] pry(main)> a.reload
[75] pry(main)> a.age
=> 18
maybe that clears it out for you. cheers
Ok so I am not sure if I actually diagnosed the problem but here is my theory on what was happening(I am not going to mark it as the answer until I give you fine folks a chance to debunk my hypothesis).
I think that since the User object doesn't actually have a password attribute(It has crypted_password and salt attributes instead) the data was getting out of sync somehow. I noticed that even when I would find the user by email and call user.password i would get a nil value in the test, but was getting the correct value from a binding in the controller.
I started by posting to the session controller create action with the new password and that worked but felt pretty dirty. I then looked into how the session controller was actually verifying the password and voila, I fixed my test to use the authenticated? method that the session controller was using. Also don't worry I cleaned up the nested if/elses as well. So my test looks like:
context "User without entitlements" do
let(:user3) { Factory(:user) }
let(:user_params_without_entitlement) { {:email => user3.email, :password => "mynewpassword", :password_confirmation => "mynewpassword", publisher_id: user3.publisher_id} }
before do
post :create, user_params_without_entitlement
end
it "updates the user password for user with no entitlement" do
User.find_by_email(user3.email).authenticated?("mynewpassword").should be_true
end
it "returns a 200 if user password is updated" do
expect(response.code).to eq('200')
end
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.