Reputation: 3285
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.
Upvotes: 0
Views: 1197
Reputation: 2280
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
Upvotes: 1
Reputation: 3285
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
Upvotes: 0
Reputation: 2280
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
Upvotes: 2