From e6c1ab2790982e700cb8b1c3bea9d1a7041f9aef Mon Sep 17 00:00:00 2001 From: marlena-b Date: Thu, 5 Sep 2024 11:24:09 +0200 Subject: [PATCH] Change Result pattern to exceptions --- .../lib/processes/reservation_process.rb | 4 +- .../controllers/client/orders_controller.rb | 14 +++--- .../app/controllers/orders_controller.rb | 17 ++++--- .../app/services/orders/submit_service.rb | 26 +++++------ rails_application/app/services/result.rb | 14 ------ .../services/orders/submit_service_test.rb | 33 +++----------- .../test/services/result_test.rb | 44 ------------------- 7 files changed, 38 insertions(+), 114 deletions(-) delete mode 100644 rails_application/app/services/result.rb delete mode 100644 rails_application/test/services/result_test.rb diff --git a/ecommerce/processes/lib/processes/reservation_process.rb b/ecommerce/processes/lib/processes/reservation_process.rb index 16c1f6dc..c3377cba 100644 --- a/ecommerce/processes/lib/processes/reservation_process.rb +++ b/ecommerce/processes/lib/processes/reservation_process.rb @@ -10,7 +10,7 @@ def call(event) state = build_state(event) case event.event_type when 'Ordering::OrderSubmitted' - order_side_effects(state) { reserve_stock(state) } + update_order_state(state) { reserve_stock(state) } when 'Fulfillment::OrderCancelled' release_stock(state) when 'Fulfillment::OrderConfirmed' @@ -38,7 +38,7 @@ def reserve_stock(state) event_store.publish(event, stream_name: stream_name(state.order_id)) end - def order_side_effects(state) + def update_order_state(state) event_store .within { yield } .subscribe(to: ReservationProcessFailed) { reject_order(state) } diff --git a/rails_application/app/controllers/client/orders_controller.rb b/rails_application/app/controllers/client/orders_controller.rb index 813899bc..37addc53 100644 --- a/rails_application/app/controllers/client/orders_controller.rb +++ b/rails_application/app/controllers/client/orders_controller.rb @@ -12,12 +12,14 @@ def new end def create - Orders::SubmitService.new(order_id: params[:order_id], customer_id: cookies[:client_id]).call.then do |result| - result.path(:success) { redirect_to client_order_path(params[:order_id]), notice: "Your order is being submitted" } - result.path(:products_out_of_stock) { |unavailable_products| redirect_to edit_client_order_path(params[:order_id]), - alert: "Order can not be submitted! #{unavailable_products.join(", ")} not available in requested quantity!"} - result.path(:order_is_empty) { redirect_to edit_client_order_path(params[:order_id]), alert: "You can't submit an empty order" } - end + Orders::SubmitService.new(order_id: params[:order_id], customer_id: cookies[:client_id]).call + rescue Orders::OrderHasUnavailableProducts => e + unavailable_products = e.unavailable_products.join(", ") + redirect_to edit_client_order_path(params[:order_id]), alert: "Order can not be submitted! #{unavailable_products} not available in requested quantity!" + rescue Ordering::Order::IsEmpty + redirect_to edit_client_order_path(params[:order_id]), alert: "You can't submit an empty order" + else + redirect_to client_order_path(params[:order_id]), notice: "Your order is being submitted" end def show diff --git a/rails_application/app/controllers/orders_controller.rb b/rails_application/app/controllers/orders_controller.rb index 0ff99611..ad926c5d 100644 --- a/rails_application/app/controllers/orders_controller.rb +++ b/rails_application/app/controllers/orders_controller.rb @@ -74,13 +74,16 @@ def remove_item end def create - Orders::SubmitService.new(order_id: params[:order_id], customer_id: params[:customer_id]).call.then do |result| - result.path(:success) { redirect_to order_path(params[:order_id]), notice: "Your order is being submitted" } - result.path(:products_out_of_stock) { |unavailable_products| redirect_to edit_order_path(params[:order_id]), - alert: "Order can not be submitted! #{unavailable_products.join(", ")} not available in requested quantity!"} - result.path(:order_is_empty) { redirect_to edit_order_path(params[:order_id]), alert: "You can't submit an empty order" } - result.path(:customer_not_exists) { redirect_to order_path(params[:order_id]), alert: "Order can not be submitted! Customer does not exist." } - end + Orders::SubmitService.new(order_id: params[:order_id], customer_id: params[:customer_id]).call + rescue Orders::OrderHasUnavailableProducts => e + unavailable_products = e.unavailable_products.join(", ") + redirect_to edit_order_path(params[:order_id]), alert: "Order can not be submitted! #{unavailable_products} not available in requested quantity!" + rescue Ordering::Order::IsEmpty + redirect_to edit_order_path(params[:order_id]), alert: "You can't submit an empty order" + rescue Crm::Customer::NotExists + redirect_to order_path(params[:order_id]), alert: "Order can not be submitted! Customer does not exist." + else + redirect_to order_path(params[:order_id]), notice: "Your order is being submitted" end def expire diff --git a/rails_application/app/services/orders/submit_service.rb b/rails_application/app/services/orders/submit_service.rb index f26f9cd9..e4eba9a1 100644 --- a/rails_application/app/services/orders/submit_service.rb +++ b/rails_application/app/services/orders/submit_service.rb @@ -1,4 +1,12 @@ module Orders + class OrderHasUnavailableProducts < StandardError + attr_reader :unavailable_products + + def initialize(unavailable_products) + @unavailable_products = unavailable_products + end + end + class SubmitService < ApplicationService def initialize(order_id:, customer_id:) @order_id = order_id @@ -6,26 +14,18 @@ def initialize(order_id:, customer_id:) end def call - success = true - unavailable_products = nil - + unavailable_products = [] event_store .within { submit_order } .subscribe(to: Processes::ReservationProcessFailed) do |event| - success = false unavailable_products = Products::Product.where(id: event.data.fetch(:unavailable_products)).pluck(:name) end .call - if success - Result.new(:success) - else - Result.new(:products_out_of_stock, unavailable_products) - end - rescue Ordering::Order::IsEmpty - Result.new(:order_is_empty) - rescue Crm::Customer::NotExists - Result.new(:customer_not_exists) + if unavailable_products.any? + raise OrderHasUnavailableProducts.new(unavailable_products) + end + true end private diff --git a/rails_application/app/services/result.rb b/rails_application/app/services/result.rb deleted file mode 100644 index 12fa1608..00000000 --- a/rails_application/app/services/result.rb +++ /dev/null @@ -1,14 +0,0 @@ -class Result - attr_reader :status, :args - - def initialize(status, *args) - @status = status - @args = args - end - - def path(name, &block) - return unless @status == name.to_sym - - block.call(*@args) - end -end diff --git a/rails_application/test/services/orders/submit_service_test.rb b/rails_application/test/services/orders/submit_service_test.rb index 6c699f50..96542571 100644 --- a/rails_application/test/services/orders/submit_service_test.rb +++ b/rails_application/test/services/orders/submit_service_test.rb @@ -13,9 +13,7 @@ def test_successful_order_submission prepare_product(product_id, "Async Remote", 49) run_command(Ordering::AddItemToBasket.new(order_id: order_id, product_id: product_id)) - result = Orders::SubmitService.new(order_id: order_id, customer_id: customer_id).call - - assert_equal result.status, :success + assert_equal true, Orders::SubmitService.new(order_id: order_id, customer_id: customer_id).call end def test_order_submission_with_unavailable_products @@ -32,32 +30,11 @@ def test_order_submission_with_unavailable_products prepare_product(another_product_id, "Fearless Refactoring", 49) run_command(Ordering::AddItemToBasket.new(order_id: order_id, product_id: another_product_id)) - result = Orders::SubmitService.new(order_id: order_id, customer_id: customer_id).call - - assert_equal result.status, :products_out_of_stock - assert_equal result.args, [["Async Remote"]] - end - - def test_order_submission_with_empty_order - order_id = SecureRandom.uuid - customer_id = SecureRandom.uuid - - result = Orders::SubmitService.new(order_id: order_id, customer_id: customer_id).call - - assert_equal result.status, :order_is_empty - end - - def test_order_submission_with_non_existing_customer - order_id = SecureRandom.uuid - customer_id = SecureRandom.uuid - product_id = SecureRandom.uuid - - prepare_product(product_id, "Async Remote", 49) - run_command(Ordering::AddItemToBasket.new(order_id: order_id, product_id: product_id)) - - result = Orders::SubmitService.new(order_id: order_id, customer_id: customer_id).call + error = assert_raises(Orders::OrderHasUnavailableProducts) do + Orders::SubmitService.new(order_id: order_id, customer_id: customer_id).call + end - assert_equal result.status, :customer_not_exists + assert_equal ["Async Remote"], error.unavailable_products end private diff --git a/rails_application/test/services/result_test.rb b/rails_application/test/services/result_test.rb deleted file mode 100644 index 78080201..00000000 --- a/rails_application/test/services/result_test.rb +++ /dev/null @@ -1,44 +0,0 @@ -require "test_helper" - -class ResultTest < InMemoryTestCase - cover Result - - def test_executes_path - result = Result.new(:first_path) - executed_path = nil - - result.path(:first_path) { executed_path = :first } - result.path(:other_path) { executed_path = :other } - - assert_equal :first, executed_path - end - - def test_executes_path_with_argument - result = Result.new(:first_path, "argument") - executed_path = nil - - result.path(:first_path) do |arg| - assert arg == "argument" - - executed_path = :first - end - result.path(:other_path) { |_arg| executed_path = :other } - - assert_equal :first, executed_path - end - - def test_executes_path_with_multiple_arguments - result = Result.new(:first_path, "argument1", "argument2") - executed_path = nil - - result.path(:first_path) do |arg1, arg2| - assert arg1 == "argument1" - assert arg2 == "argument2" - - executed_path = :first - end - result.path(:other_path) { |_arg| executed_path = :other } - - assert_equal :first, executed_path - end -end