ruby_newbie
ruby_newbie

Reputation: 3285

Rails 3.2 reload! not working as expected

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

Answers (3)

Tim Kretschmer
Tim Kretschmer

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

ruby_newbie
ruby_newbie

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

Tim Kretschmer
Tim Kretschmer

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

Related Questions