I’ve got a process where user can activate a code that they’ve received: the activation process should do the following:
- Add X credits to the user account (User.credits)
- Create new creditlog item (just for history purposes)
- Mark the code as activated, so that user can not activate it again.
I’m having a specific controller for this task. I created a method “code_activate”, that works. But it’s not ACID compliant, I believe. Should this be a method in some model (user?), or in a controller as I’ve done it? How would you implement it “the correct way”?
Here’s the code:
def code_activate
code = CreditCodes.find_by_code(params[:code])
unless code
render :json => { :success=>false, :message=>(t :codedoesnotexist)}
return
end
if code.activated
render :json => { :success=>false, :message=>(t :codealreadyactivated)}
return
end
# Add credits to user
current_user.credits += code.amount
current_user.save
# Save credit log record
cl = current_user.creditlog.new
cl.actionid = 1
cl.amount = code.amount
cl.save
# Set code as activated
code.activated = true
code.save
# Show success message
render :json => { :success=>true, :message=>((t :creditsadded).gsub(/@AMOUNT@/, code.amount.to_s)) }, :status => :ok
end
It’s business logic. It belongs into the model (CreditCode most likely)
You want to put this in a transaction to ensure that adding the amount and marking the code happens all or nothing.
Assume in your CreditCode you define a activate method like this: