Instantly share code, notes, and snippets.

@nicoolas25 /after.rb Secret
Created Jul 8, 2017

Embed
What would you like to do?
Refactoring for drivy.engineering blog (Ruby 2.5)
class ConfirmOrder < Command
def initialize(order, payment_token, notify: true)
@order = order
@payment_token = payment_token
@notify = notify
end
validate do
payment_token_must_be_valid
payment_amount_must_match_sales_quote
end
perform do
capture_payment!
create_invoice_and_update_status
send_notifications
rescue Payment::CaptureError
add_error(:payment_capture_error)
end
private
def payment
@payment ||= @order.payments.new(token: @payment_token)
end
def payment_token_must_be_valid
add_error(:payment_token_invalid) unless payment.valid?
end
def payment_amount_must_match_sales_quote
add_error(:payment_amount_mismatch) unless payment_amount_match_sales_quote?
end
def payment_amount_match_sales_quote?
payment.amount == @order.sales_quote.amount &&
payment.currency == @order.sales_quote.currency
end
def capture_payment!
payment.save!
payment.capture!
end
def create_invoice_and_update_status
Order.transaction do
create_invoice
update_status
end
end
def create_invoice
invoice = @order.invoices.create!({
amount: @order.sales_quote.amount,
currency: @order.sales_quote.currency,
})
@order.sales_quote.items.find_each do |item|
invoice.items.create!({
product_id: item.product_id,
quantity: item.quantity,
unit_price: item.unit_price,
})
end
end
def update_order_status
@order.update(status: :confirmed)
end
def send_notifications
return unless @notify
OrderMailer.preparation_details(@order).deliver_async
OrderMailer.confirmation(@order).deliver_async
OrderMailer.available_invoice(@order).deliver_async
end
end
class ConfirmOrder < Command
def initialize(order, payment_token, notify: true)
@order = order
@payment_token = payment_token
@notify = notify
end
validate do
payment = @order.payments.new(token: @payment_token)
if !payment.valid?
add_error(:payment_token_invalid)
end
if payment.amount != @order.sales_quote.amount || payment.currency != @order.sales_quote.currency
add_error(:payment_amount_mismatch)
end
end
perform do
@order.payments.create!(token: @payment_token).capture!
Order.transaction do
invoice = @order.invoices.create!({
amount: @order.sales_quote.amount,
currency: @order.sales_quote.currency,
})
sales_quote.items.find_each do |item|
invoice.items.create!({
product_id: item.product_id,
quantity: item.quantity,
unit_price: item.unit_price,
})
end
@order.update(status: :confirmed)
end
if @notify
OrderMailer.preparation_details(@order).deliver_async
OrderMailer.confirmation(@order).deliver_async
OrderMailer.available_invoice(@order).deliver_async
end
rescue Payment::CaptureError => error
add_error(:payment_capture_error)
end
end
@julien-meichelbeck

This comment has been minimized.

Copy link

julien-meichelbeck commented Nov 3, 2017

Hey, I'm wondering about the implementation of your Command class. Is there a difference between validate and perform? Is it just semantical ? So the Command#perform! method basically calls those two blocks ?

@manojmj92

This comment has been minimized.

Copy link

manojmj92 commented Nov 9, 2017

Can you include implementation of Command class as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment