Skip to content

Instantly share code, notes, and snippets.

@DmytroVasin
Created May 2, 2017 08:39
Show Gist options
  • Select an option

  • Save DmytroVasin/490523c7548d328dd20d08ad8ca1a974 to your computer and use it in GitHub Desktop.

Select an option

Save DmytroVasin/490523c7548d328dd20d08ad8ca1a974 to your computer and use it in GitHub Desktop.
Service Objects
class TripReservationsController < ApplicationController
def create
reservation = TripReservation.new(params[:trip_reservation])
trip = Trip.find_by_id(reservation.trip_id)
agency = trip.agency
payment_adapter = PaymentAdapter.new(buyer: current_user)
unless current_user.can_book_from?(agency)
redirect_to trip_reservations_page, notice: TripReservationNotice.new(:agency_rejection)
end
unless trip.has_free_tickets?
redirect_to trip_reservations_page, notice: TripReservationNotice.new(:tickets_sold)
end
begin
receipt = payment_adapter.pay(trip.price)
reservation.receipt_id = receipt.uuid
unless reservation.save
logger.info "Failed to save reservation: #{reservation.errors.inspect}"
redirect_to trip_reservations_page, notice: TripReservationNotice.new(:save_failed)
end
redirect_to trip_reservations_page(reservation), notice: :reservation_booked
rescue PaymentError => e
logger.info "#{current_user.name} failed to pay for #{trip.name}: #{e.message}"
redirect_to trip_reservations_page, notice: TripReservationNotice.new(:payment_failed, reason: e.message )
end
end
end
class TripReservationsController < ApplicationController
def create
user = current_user
trip = Trip.find_by_id(reservation.trip_id)
agency = trip.agency
reservation = TripReservation.new(params[:trip_reservation])
begin
trip_reservation_service.process(user, trip, agency, reservation)
redirect_to trip_reservations_page(reservation), notice: :reservation_booked
rescue TripReservationService::TripPaymentError => e
redirect_to trip_reservations_page, notice: TripReservationNotice.new(:payment_failed, reason: e.message)
rescue TripReservationService::ReservationError
redirect_to trip_reservations_page, notice: TripReservationNotice.new(:save_failed)
rescue TripReservationService::NoTicketError
redirect_to trip_reservations_page, notice: TripReservationNotice.new(:tickets_sold)
rescue TripReservationService::AgencyRejectionError
redirect_to trip_reservations_page, notice: TripReservationNotice.new(:agency_rejection)
end
end
private
def trip_reservation_service
TripReservationService.new( PaymentAdapter(buyer: current_user), logger )
end
end
class TripReservationService
class TripPaymentError < StandardError; end
class ReservationError < StandardError; end
class NoTicketError < StandardError; end
class AgencyRejectionError < StandardError; end
attr_reader :payment_adapter, :logger
def initialize(payment_adapter, logger)
@payment_adapter = payment_adapter
@logger = logger
end
def process(user, trip, agency, reservation)
raise AgencyRejectionError.new unless user.can_book_from?(agency)
raise NoTicketError.new unless trip.has_free_tickets?
begin
receipt = payment_adapter.pay(trip.price)
reservation.receipt_id = receipt.uuid
unless reservation.save
logger.info "Failed to save reservation: #{reservation.errors.inspect}"
raise ReservationError.new
end
rescue PaymentError => e
logger.info "#{user.name} failed to pay for #{trip.name}: #{e.message}"
raise TripPaymentError.new e.message
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment