Last active
August 11, 2020 08:45
-
-
Save yowchun93/2079478f22197dd2891055f7e5048d51 to your computer and use it in GitHub Desktop.
Refactoring using OOP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# CheckoutService takes a cart, and checkouts each cart items | |
class CheckoutService | |
def initialize(cart, params) | |
@cart = cart | |
@params = params | |
end | |
def run | |
create_order | |
if order_approved? && cart.checked_out_at.nil? | |
create_credits | |
lift_reservation_restrictions | |
fulfill_items | |
checkout_cart | |
deliver_order_success_email if order_completed? | |
end | |
end | |
def create_credits | |
CreditAllocationService.call(@cart) | |
end | |
def lift_reservation_restrictions | |
Checkout::LiftReservationRestrictionService.call(@cart) | |
end | |
end | |
# CreditAllocationService goes through each cart items, and creates credit for user | |
# Hidden object here is 'packages' | |
class CreditAllocationService | |
def initialize(cart) | |
@cart = cart | |
@user = @cart.user | |
end | |
def call | |
packages.each do |package| | |
# TODO: Remove number_of_sessions after products | |
next if package.number_of_sessions == 0 | |
@user.credits << credit_for_package(package) | |
end | |
@user.save! | |
end | |
def self.call(cart) | |
new(cart).call | |
end | |
private | |
def credit_for_package(package) | |
@user.credits.new do |credit| | |
credit.status = :active | |
credit.cart_item_id = package.cart_item_id | |
credit.count = package.number_of_credits | |
credit.credit_type = package.credit_type | |
credit.expires_at = package.expires_at | |
credit.number_of_sessions = package.number_of_credits | |
credit.unlimited = package.unlimited? | |
credit.unlimited_validity = package.unlimited_validity? | |
credit.daily_limit = package.daily_limit | |
end | |
end | |
def packages | |
@cart.cart_items.creditable.includes(:purchasable).map do |item| | |
PackageDecorator.new(item) | |
end | |
end | |
end | |
# LiftReservationRestrictionService goes through each reservation_restriction and updates it to paid | |
class Checkout::LiftReservationRestrictionService | |
def self.call(cart) | |
cart.reservation_restrictions.update_all(paid_at: Time.now) | |
end | |
end | |
# Goal of the refactor is to find a common interface for | |
# packages and reservation restriction | |
# therefore we introduce #fulfill as the common interface | |
# Refactored version | |
class CheckoutService | |
attr_reader :params, :cart, :order | |
def initialize(cart, params) | |
@cart = cart | |
@params = params | |
end | |
def run | |
create_order | |
if order_approved? && cart.checked_out_at.nil? | |
fulfill_items | |
checkout_cart | |
deliver_order_success_email if order_completed? | |
end | |
end | |
private | |
def fulfill_items | |
cart.cart_items.each do |item| | |
fulfillment_klass_for(item).new(item).fulfill | |
end | |
end | |
def fulfillment_klass_for(item) | |
"Fulfillment::#{item.purchasable.class}".constantize | |
end | |
end | |
class Fulfillment::Package | |
def initialize(cart_item) | |
@cart_item = cart_item | |
@package = cart_item.package | |
@user = cart_item.user | |
end | |
def fulfill | |
# TODO: Remove number_of_sessions after products | |
return if @package.number_of_sessions == 0 | |
@user.credits.create do |credit| | |
credit.status = :active | |
credit.cart_item_id = @cart_item.id | |
credit.count = number_of_credits | |
credit.credit_type = @package.credit_type | |
credit.expires_at = expires_at | |
credit.number_of_sessions = number_of_credits | |
credit.unlimited = @package.unlimited? | |
credit.unlimited_validity = @package.unlimited_validity? | |
credit.daily_limit = @package.daily_limit | |
end | |
end | |
private | |
def number_of_credits | |
return if @package.unlimited? | |
@package.number_of_sessions * @cart_item.quantity | |
end | |
def expires_at | |
return if @package.unlimited_validity? | |
Time.current + (@package.validity_period_days.days * @cart_item.quantity) | |
end | |
end | |
class Fulfillment::ReservationRestriction | |
def initialize(cart_item) | |
@reservation_restriction = cart_item.purchasable | |
end | |
def fulfill | |
@reservation_restriction.update(paid_at: Time.now) | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment