I have 2 models User.rb
and Client.rb
. Relationship is:
User.rb
has_and_belongs_to_many :clients, inverse_of: :users
Client
has_and_belongs_to_many :users, inverse_of: :clients
Callbacks in User.rb
model
after_create :client_not_erasable
after_update :assign_client
def client_not_erasable
.
.
end
def assign_client
def to_param
return Client.find(client_to_add) unless client_to_add.nil?
end
unless client_to_add.nil?
if to_param.users.count.zero? && client_to_add.present?
to_param.update_attributes(erasable:false)
end
end
end
First callback after_create :client_not_erasable
is working fine, but second callback after_update :assign_client
doesn't work. I'm getting true. I should get false
describe 'after_save and after_update callbacks' do
let(:user) { build(:user) }
let(:client) { build(:client) }
it 'erasable client field should be false after of an user create' do
user.clients.count == 1
user.clients[0].erasable = true
user.run_callbacks :create
expect(user.clients[0].erasable).to be(false)
end
it 'erasable client field should be false after of it is assigned to user' do
client.erasable = true
user.run_callbacks :update
expect(client.erasable).to be(false)
end
end
Testing result:
Failures:
1) User Validations after_save and after_update erasable client field should be false after of it is assigned to user
Failure/Error: expect(client.erasable).to be(false)
expected false
got true
# ./spec/models/user_spec.rb:93:in `block (4 levels) in <top (required)>'
thank you!
Thank you to yzalavin response. the code that is finally working fine is:
context 'Hooks' do
let(:client) { build(:client) }
let(:user) { build(:user) }
let!(:users) { create_list(:user, 2, clients: [client]) }
it 'erasable client field should be false after of an user create' do
user.clients.count == 1
user.clients[0].erasable = true
user.run_callbacks :create
expect(user.clients[0].erasable).to be(false)
end
it 'erasable client field should be false after of it is assigned to user' do
client.erasable = true
user.run_callbacks :update
expect(client.reload.erasable).to be(false)
end
end
Thank you