In my model definition, I have
# models/my_model.rb
# == Schema Information
#
# Table name: my_models
#
# id :bigint not null, primary key
# another_model_id :bigint
# field_1 :string
# field_2 :string
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_my_models_on_another_model_id (another_model_id) UNIQUE
class MyModel < ApplicationRecord
belongs_to :another_model
def update_from_api_response(api_response)
$stderr.puts("UPDATE")
self.field_1 = api_response[:field_1]
self.field_2 = api_response[:field_2]
end
def update_my_model!(api_response)
ApplicationRecord.transaction do
$stderr.puts("HELLO")
update_from_api_response(api_response)
$stderr.puts("WORLD")
self.save!
end
end
end
I put in some puts
statements to check whether my code entered the function. If everything works alright, the program should log "HELLO", "UPDATE", then "WORLD".
In my model spec I have
# spec/models/my_model_spec.rb
RSpec.describe MyModel, type: :model do
let(:my_model) { create(:my_model) }
let(:api_response) {
{
:field_1 => "field_1",
:field_2 => "field_2",
}
}
describe("update_my_model") do
it "should update db record" do
expect(my_model).to receive(:update_from_api_response)
.with(api_response)
expect(my_model).to receive(:save!)
expect{ my_model.update_my_model!(api_response) }
.to change{ my_model.field_1 }
end
end
end
The factory object for MyModel
is defined like this (it literally does not do anything)
# spec/factories/my_models.rb
FactoryBot.define do
factory :my_model do
end
end
The output from the puts
(this appears before the error message)
HELLO
WORLD
Interestingly, "UPDATE" is not printed, but it passes the receive
test.
The change
match test fails, and the output from the console is as follows
1) MyModel update_my_model should update db record
Failure/Error:
expect{ my_model.update_my_model(api_response) }
.to change{ my_model.field_1 }
expected `my_model.field_1` to have changed, but is still nil
# ./spec/models/my_model_spec.rb
# ./spec/rails_helper.rb
I suspected that it might have something to do with me wrapping the update within ApplicationRecord.transaction do
but removing that does nothing as well. "UPDATE" is not printed in both cases.
I've also changed the .to receive(:update_from_api_response)
to .to_not receive(:updated_from_api_response)
but it throws an error saying that the function was called (but why is "UPDATE" not printed then?). Is there something wrong with the way I'm updating my functions? I'm new to Ruby so this whole self
syntax and whatnot is unfamiliar and counter-intuitive. I'm not sure if I "updated" my model field correctly.
Thanks!
Link to Git repo: https://github.com/jzheng13/rails-tutorial.git