From fcdc80c9d24123f6b2015396dd65faaffcf8328c Mon Sep 17 00:00:00 2001 From: Alex Tharp Date: Tue, 7 Aug 2018 09:04:44 -0400 Subject: [PATCH 1/3] refactor(Transactions): migrate from exceptions as control flow to railway/functional error handling --- .../cortex/content_items_controller.rb | 64 +++++++++++-------- app/helpers/cortex/content_item_helper.rb | 39 ++++++----- .../cortex/database_transact_operation.rb | 13 ++-- .../cortex/persist_content_item_operation.rb | 7 +- 4 files changed, 71 insertions(+), 52 deletions(-) diff --git a/app/controllers/cortex/content_items_controller.rb b/app/controllers/cortex/content_items_controller.rb index f7c966edd..fe480f505 100644 --- a/app/controllers/cortex/content_items_controller.rb +++ b/app/controllers/cortex/content_items_controller.rb @@ -28,47 +28,57 @@ def edit @content_item = content_type.content_items.find_by_tenant(current_user.active_tenant).find_by_id(params[:id]) @wizard = wizard_decorator(@content_item.content_type) - title = @content_item.field_items.find { |field_item| field_item.field.name == 'Title' }.data['text'] # TODO: refactor this hardcoded Field reference + title = @content_item.field_items.find {|field_item| field_item.field.name == 'Title'}.data['text'] # TODO: refactor this hardcoded Field reference add_breadcrumb content_type.name.pluralize, :content_type_content_items_path add_breadcrumb title add_breadcrumb 'Edit' end def update - begin - update_content_item - rescue ActiveRecord::RecordInvalid => e - flash[:warning] = validation_message(e.message) - @content_item = content_item_reload(content_type.content_items.find_by_id(params[:id])) - @wizard = wizard_decorator(@content_item.content_type) + update_content_item + .with_step_args( + execute_content_item_state_change: [state: params[:content_item][:state]] + ) + .call(id: params[:id], content_type: content_type, + content_item_params: content_item_params, current_user: current_user) do |m| + m.success do |content_item| + flash[:success] = "#{content_type.name} successfully updated" + redirect_to content_type_content_items_path + end - title = @content_item.field_items.find { |field_item| field_item.field.name == 'Title' }.data['text'] # TODO: refactor this hardcoded Field reference - add_breadcrumb content_type.name.pluralize, :content_type_content_items_path - add_breadcrumb title - add_breadcrumb 'Edit' + m.failure :persist_content_item do |errors| + flash[:warning] = clean_error_messages(errors.full_messages) + render_update_content_item_error + end - render :edit - else - flash[:success] = "Hooray! #{content_type.name} Updated!" - redirect_to content_type_content_items_path + m.failure do |error| + flash[:warning] = ['Unknown System Error'] + render_update_content_item_error + end end end def create - begin - create_content_item - rescue ActiveRecord::RecordInvalid => e - flash[:warning] = validation_message(e.message) - @content_item = content_item_reload(content_type.content_items.new) - @wizard = wizard_decorator(@content_item.content_type) + create_content_item + .with_step_args( + execute_content_item_state_change: [state: params[:content_item][:state]] + ) + .call(id: params[:id], content_type: content_type, + content_item_params: content_item_params, current_user: current_user) do |m| + m.success do |content_item| + flash[:success] = "#{content_type.name} successfully created" + redirect_to content_type_content_items_path + end - add_breadcrumb content_type.name.pluralize, :content_type_content_items_path - add_breadcrumb 'New' + m.failure :persist_content_item do |errors| + flash[:warning] = clean_error_messages(errors.full_messages) + render_create_content_item_error + end - render :new - else - flash[:success] = "Hooray! #{content_type.name} Created!" - redirect_to content_type_content_items_path + m.failure do |error| + flash[:warning] = ['Unknown System Error'] + render_update_content_item_error + end end end end diff --git a/app/helpers/cortex/content_item_helper.rb b/app/helpers/cortex/content_item_helper.rb index a7c473ea5..4844f3e74 100644 --- a/app/helpers/cortex/content_item_helper.rb +++ b/app/helpers/cortex/content_item_helper.rb @@ -6,22 +6,32 @@ def content_type def create_content_item CreateContentItemTransaction.new - .with_step_args( - execute_content_item_state_change: [state: params[:content_item][:state]] - ) - .call(id: params[:id], content_type: content_type, - content_item_params: content_item_params, current_user: current_user) - .value! end def update_content_item UpdateContentItemTransaction.new - .with_step_args( - execute_content_item_state_change: [state: params[:content_item][:state]] - ) - .call(id: params[:id], content_type: content_type, - content_item_params: content_item_params, current_user: current_user) - .value! + end + + def render_create_content_item_error + @content_item = content_item_reload(content_type.content_items.new) + @wizard = wizard_decorator(@content_item.content_type) + + add_breadcrumb content_type.name.pluralize, :content_type_content_items_path + add_breadcrumb 'New' + + render :new + end + + def render_update_content_item_error + @content_item = content_item_reload(content_type.content_items.find_by_id(params[:id])) + @wizard = wizard_decorator(@content_item.content_type) + + title = @content_item.field_items.find { |field_item| field_item.field.name == 'Title' }.data['text'] # TODO: refactor this hardcoded Field reference + add_breadcrumb content_type.name.pluralize, :content_type_content_items_path + add_breadcrumb title + add_breadcrumb 'Edit' + + render :edit end def content_item_reload(content_item) @@ -98,9 +108,8 @@ def field_item_param_data(field_item_params) params_hash['data'] || {} end - def validation_message(base_message) - msg_array = base_message.gsub('Validation failed:', '').gsub('Field items', '').split(',') - msg_array.map {|message| message.strip.titleize} + def clean_error_messages(messages) + messages.map {|message| message.gsub('Field items', '').strip.titleize} end end end diff --git a/app/operations/cortex/database_transact_operation.rb b/app/operations/cortex/database_transact_operation.rb index 5c30935ad..fca527679 100644 --- a/app/operations/cortex/database_transact_operation.rb +++ b/app/operations/cortex/database_transact_operation.rb @@ -4,14 +4,11 @@ module Cortex result = nil - begin - ActiveRecord::Base.transaction do - result = block.(Success(input)) - raise ActiveRecord::Rollback if result.failure? - result - end - rescue ActiveRecord::Rollback - result + ActiveRecord::Base.transaction do + result = block.(Success(input)) + raise ActiveRecord::Rollback if result.failure? end + + result } end diff --git a/app/operations/cortex/persist_content_item_operation.rb b/app/operations/cortex/persist_content_item_operation.rb index 98fe001e8..53d9fd5a8 100644 --- a/app/operations/cortex/persist_content_item_operation.rb +++ b/app/operations/cortex/persist_content_item_operation.rb @@ -5,8 +5,11 @@ class PersistContentItemOperation include Dry::Transaction::Operation def call(input) - input.save! - Success(input) + if input.save + Success(input) + else + Failure(input.errors) + end end end end From 8ee9775a945e423020741a23495a5bf7a8b3577b Mon Sep 17 00:00:00 2001 From: Alex Tharp Date: Tue, 7 Aug 2018 09:05:19 -0400 Subject: [PATCH 2/3] fix(Media CRUD): temporarily return to Cell rendering for Media ContentType --- app/views/cortex/content_items/_form.html.haml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/views/cortex/content_items/_form.html.haml b/app/views/cortex/content_items/_form.html.haml index 79a853942..726e49e7f 100644 --- a/app/views/cortex/content_items/_form.html.haml +++ b/app/views/cortex/content_items/_form.html.haml @@ -1,11 +1,11 @@ = form_for [@content_type, @content_item], html: { multipart: true } do |form| = form.hidden_field :creator_id, value: current_user.id = form.hidden_field :content_type_id, value: @content_type.id - -# TODO: remove conditional once cortex plugins fields are properly converted - - if @content_type.name == 'Media' - = react_component('CortexApp', props: { temporary_render: 'Wizard' }) - - else - = cell(Cortex::WizardCell, @wizard, context: { content_item: @content_item, form: form }).() + -# TODO: remove conditional once fields are properly converted to React + -# if @content_type.name == 'Media' + =# react_component('CortexApp', props: { temporary_render: 'Wizard' }) + -# else + = cell(Cortex::WizardCell, @wizard, context: { content_item: @content_item, form: form }).() %footer.mdl-grid .mdl-cell.mdl-cell--12-col From 93e716de3fc19b90b4d7ad860fb0ffb64881d5e1 Mon Sep 17 00:00:00 2001 From: Alex Tharp Date: Tue, 7 Aug 2018 09:06:13 -0400 Subject: [PATCH 3/3] chore(Gemfile.lock): bump cortex --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6bb816747..5fdb82076 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - cortex (0.1.0) + cortex (0.1.1) addressable (~> 2.5.2) awesome_nested_set (~> 3.1.4) breadcrumbs_on_rails (~> 3.0.1)