amingilani amingilani - 7 months ago 11
Ruby Question

Rails: how do I set an attribute just by calling it

I'm trying to get

@user.stripe_customer_id
to return a string. If it isn't set, then it should run a call to an external service, set it, and return it.

More verbosely here are my tests:

context 'Stripe ID' do
it 'should not be writable' do
expect { @user.stripe_customer_id = 'random_id_123123' }
.to raise_error(NoMethodError)
end

it 'should be generated if it does not exist' do
@user.save
expect(@user.stripe_customer_id).to include('cus')
end
end


where
@user
is a valid
User << ActiveRecord
instance.

Rspec fails with the following:

Failed examples:

rspec ./spec/models/user_spec.rb:87 # User Stripe ID should be generated if it does not exist


And the
User.rb
file has the following lines:

def stripe_customer_id
if stripe_customer_id.blank?
stripe = Stripe::Customer.create(
description: "Username: #{username}",
email: email
)
self.stripe_customer_id = stripe.id
save!
end
stripe_customer_id
end

private

def stripe_customer_id=(new_customer_id)
write_attribute(:stripe_customer_id, new_customer_id)
end

Answer

You are trying to overwrite the getter method for stripe_customer_id

def stripe_customer_id
  self[:stripe_customer_id] || write_attribute(:stripe_customer_id, new_customer_id)
end

This is an untested code which i just wrote up. But i'm pretty sure this should work for your case. Please give it a try an let me know.