Skip to content

Instantly share code, notes, and snippets.

@nicoolas25
Created July 8, 2017 17:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nicoolas25/d3297e9e10e870787c6a40431c2ffa88 to your computer and use it in GitHub Desktop.
Save nicoolas25/d3297e9e10e870787c6a40431c2ffa88 to your computer and use it in GitHub Desktop.
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
Copy link

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
Copy link

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