From 8da3e8ebe1b6e9d7e518bcfc46049950ceb0aca4 Mon Sep 17 00:00:00 2001 From: andrea longhi Date: Fri, 30 Oct 2020 17:23:17 +0100 Subject: [PATCH] Decorate `Spree::UsersController` when already existing This commit allows to decorate the class `Spree::UsersController` when already present (ie. when it's already included in the gem `solidus_frontend`) or to define the class from scratch when it's not (ie. when using a version of Solidus where `solidus_frontend` does not include it). See solidusio/solidus#2695 for the PR that adds the account page to Solidus Frontend. Once all supported versions of Solidus include the account page, we will be able to get rid of the class definition, together with the ERB view at `lib/views/frontend/spree/users/show.html.erb`. --- .../frontend/spree/users_controller.rb | 65 -------------- .../spree/users_controller_decorator.rb | 87 +++++++++++++++++++ 2 files changed, 87 insertions(+), 65 deletions(-) delete mode 100644 lib/controllers/frontend/spree/users_controller.rb create mode 100644 lib/decorators/frontend/controllers/spree/users_controller_decorator.rb diff --git a/lib/controllers/frontend/spree/users_controller.rb b/lib/controllers/frontend/spree/users_controller.rb deleted file mode 100644 index 81ecc60b..00000000 --- a/lib/controllers/frontend/spree/users_controller.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true - -class Spree::UsersController < Spree::StoreController - skip_before_action :set_current_order, only: :show, raise: false - prepend_before_action :load_object, only: [:show, :edit, :update] - prepend_before_action :authorize_actions, only: :new - - include Spree::Core::ControllerHelpers - - def show - @orders = @user.orders.complete.order('completed_at desc') - end - - def create - @user = Spree::User.new(user_params) - if @user.save - - if current_order - session[:guest_token] = nil - end - - redirect_back_or_default(root_url) - else - render :new - end - end - - def update - if @user.update(user_params) - spree_current_user.reload - redirect_url = spree.account_url - - if params[:user][:password].present? - # this logic needed b/c devise wants to log us out after password changes - if Spree::Auth::Config[:signout_after_password_change] - redirect_url = spree.login_url - else - bypass_sign_in(@user) - end - end - redirect_to redirect_url, notice: I18n.t('spree.account_updated') - else - render :edit - end - end - - private - - def user_params - params.require(:user).permit(Spree::PermittedAttributes.user_attributes | [:email]) - end - - def load_object - @user ||= Spree::User.find_by(id: spree_current_user&.id) - authorize! params[:action].to_sym, @user - end - - def authorize_actions - authorize! params[:action].to_sym, Spree::User.new - end - - def accurate_title - I18n.t('spree.my_account') - end -end diff --git a/lib/decorators/frontend/controllers/spree/users_controller_decorator.rb b/lib/decorators/frontend/controllers/spree/users_controller_decorator.rb new file mode 100644 index 00000000..4e73bc9c --- /dev/null +++ b/lib/decorators/frontend/controllers/spree/users_controller_decorator.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +module Spree + module UsersControllerDecorator + def self.prepended(base) + base.prepend_before_action :authorize_actions, only: :new + base.prepend_before_action :load_object, only: [:show, :edit, :update] + end + + def create + @user = Spree::User.new(user_params) + if @user.save + + if current_order + session[:guest_token] = nil + end + + redirect_back_or_default(root_url) + else + render :new + end + end + + def update + if @user.update(user_params) + spree_current_user.reload + redirect_url = spree.account_url + + if params[:user][:password].present? + # this logic needed b/c devise wants to log us out after password changes + if Spree::Auth::Config[:signout_after_password_change] + redirect_url = spree.login_url + else + bypass_sign_in(@user) + end + end + redirect_to redirect_url, notice: I18n.t('spree.account_updated') + else + render :edit + end + end + + private + + def user_params + params.require(:user).permit(Spree::PermittedAttributes.user_attributes | [:email]) + end + + def authorize_actions + authorize! params[:action].to_sym, Spree::User.new + end + + # When using a version of Solidus that includes the account page, we just need to + # decorate the existing controller with further behavior from this extension. + # + # On the other hand, when using a version of Solidus that does not include the + # account page, we need to define the controller from scratch. + # + # Once we drop the support for all Solidus versions that don't include the + # account page, we can just leave the decorator and remove anything else, including + # the view file at `lib/views/frontend/spree/users/show.html.erb`. + if defined?(Spree::UsersController) + Spree::UsersController.prepend(self) + else + class Spree::UsersController < Spree::StoreController + skip_before_action :set_current_order, only: :show, raise: false + + include Spree::Core::ControllerHelpers + + def show + @orders = @user.orders.complete.order('completed_at desc') + end + + def load_object + @user ||= Spree::User.find_by(id: spree_current_user&.id) + authorize! params[:action].to_sym, @user + end + + def accurate_title + I18n.t('spree.my_account') + end + + prepend Spree::UsersControllerDecorator + end + end + end +end