borjagvo
borjagvo

Reputation: 2071

Expected behavior FactoryBot

I'm testing a rake task - update_city_status_for_users:

task update_city_status_for_users: :environment do
    User.update_city_statuses do |user, new_status|
        # does something
    end
end 

Method User.update_city_statuses:

def self.update_city_statuses(&block)
    users_ids = Journey.valid.where.not(user_id: nil).pluck(:user_id) # Only journeys (valid) for route 1
    users_with_journeys = self.where(id: users_ids)

    Rails.logger.info "Only update users with at least one journey: #{users_with_journeys.count} users to update."

    ActiveRecord::Base.transaction do
      users_with_journeys.each do |u|
            new_status = u.new_status? 
            if new_status != nil
                begin
                    u.update!(city_status: new_status)
                    yield(u,new_status) if block_given?
                rescue => exception
                    Rails.logger.error "Exception updating user with id #{u.id}. Exception: "+exception.to_s
                end
            end
        end
    end
  end

And this is the test:

RSpec.describe do 
    describe "update_city_status_for_users" do
        it 'updates users with their corespondent new city status: from nil to "Venice"' do

            user = user_with_journeys(5, "Venice")
            city_status_before_task = user.city_status

            BicycleIsland::Application.load_tasks
            Rake::Task['update_city_status_for_users'].invoke

            expect(city_status_before_task).to eq nil
            expect(user.city_status).to be_an_instance_of CityStatus
            expect(user.city_status.city).to eq "Venice"
        end
    end
end

user_with_journeys is defined where the user factories are and basically it creates a user with 5 journeys.

After task invocation inside the test I check the user variable (factory created):

user.city_status 
# nil

However, when I pull the user from the database the association has been made and city_status is not nil:

User.find(user.id).city_status 
# #<CityStatus id: 6, level: 6, city: "Venice", distance: 1730, created_at: "2020-11-18 17:11:32", updated_at: "2020-11-18 17:11:32", image_file_name: "Venice-1000.png">

Both users are the same:

User.find(user.id) == user
# true

However, the city_status is not associated when calling the factory directly. That's not the behavior I was expecting. I would expect to carry on the updates and associations that have been made.

I'm probably missing something? Could anyone help me to point it out?

Thanks!

Upvotes: 0

Views: 210

Answers (1)

Anuj
Anuj

Reputation: 1940

Rails caches the model instances to avoid repetitive database queries. You'll need to call

user.reload

before your assertions to update the object with the latest values from the database.

Upvotes: 1

Related Questions