在rails应用程序中对非常相似的控制器使用继承



我有一个rails应用程序,它有两个行为非常相似的控制器。一个是与酒店概念相关的UsersController,另一个也被命名为UsersCoontroller,但与关联概念相关,因此它存储在文件夹关联中:class Api::V1::Association::UsersController < Api::V1::BaseController

这些控制器有非常相似的行为,方法略有不同(它们对某些变量依赖于不同的数据库表…)。我读过关于继承的文章,认为让Association::UsersControllerUsersController继承可能很有趣。你认为这对我来说是正确的做法吗?例如,我一直试图重写Association::UsersController的方法invite以使用继承,但我有点困惑。你能告诉我如果Association::UsersController继承自usersController,你将如何重写这个方法吗。以下是两个控制器的样子:

users_controller.rb:

class Api::V1::UsersController < Api::V1::BaseController
  skip_after_action :verify_authorized, only: [:invite, :update_specific, :show]
  before_action :set_user, except: [:invite, :index, :update_specific]
  before_action :set_account, only: [:index, :invite, :show]
  # creates user linked to account / only account owner can create users linked to account
  # input account_id & email
  def invite
    unless current_user.id != @account.admin_user_id
      user_already_exists_or_email_blank?
      set_new_user
      ActiveRecord::Base.transaction do
        set_hotels_access
        save_user_and_send_invitation_email
      end
    else
      render_error("not_admin")
    end
  end
  def show
    if ((current_user == @user) || (@account.admin == current_user))
    else
      render_error("unauthorized")
    end
  end
  # admin can update employee or manager
  def update_specific
    @user_to_update = User.find(params[:id])
    if @user_to_update.account != current_user.created_account
      render_error("unauthorized")
    else
      ActiveRecord::Base.transaction do
        update_user_and_hotels_access
      end
    end
  end
  # update self
  def update
    authorize @user
    if @user.update(user_params)
      render_success("updated")
    else
      render_error("")
    end
  end
  def destroy
    authorize @user
    if @user.destroy
      render json: {message: "User successfully destroyed"}
    else
      render json: {error: "There was an error please try again"}
    end
  end
  # envoyer account params
  def index
    if (current_user.created_account == @account) || ((current_user.account == @account) && (current_user.status == "manager"))
      @users = policy_scope(User).where(account: @account)
      @admin = @account.admin
      render json: {users: @users, admin: @admin}
    else
      render json: {message: "Unauthorized"}
    end
  end
  # unlincks user from account
  #input user_id
  def unlinck
    authorize @user
    @user.account = nil
    if @user.save && @user.hotels.delete_all.nil?
      render json: {user: @user}
    else
      render_error("db")
    end
  end
  private
  def user_already_exists_or_email_blank?
    if User.find_by_email(params[:user][:email])
      render_error("mail_exists") and return
    elsif params[:user][:email].blank?
      render_error("empty_email") and return
    end
  end
  def set_new_user
    password = SecureRandom.hex
    invitation_token = SecureRandom.uuid
    @user = User.new(first_name: params[:user][:first_name], last_name: params[:user][:last_name], telephone: params[:user][:telephone], account_id: params[:user][:account_id], email: params[:user][:email], status: params[:user][:status], password: password, password_confirmation: password, invitation_token: invitation_token, invitation_created_at: Time.now, role: "hotel")
  end
  def set_hotels_access
    if params[:hotel_access].first == "all"
      @hotels = @account.hotels
    else
      @hotels = Hotel.where(id: params[:hotel_access])
    end
  end
  def save_user_and_send_invitation_email
    if @user.save && @user.hotels << @hotels
      if UserMailer.send_invitation(@user, params[:app_base_url]).deliver_now
        @user.invitation_sent_at = Time.now
        if @user.save
          render_success("mail_sent")
        else
          render_error("db")
        end
      else
        render_error("mail_processing")
      end
    else
      render_error("db")
    end
  end
  def update_user_and_hotels_access
    @hotels = Hotel.where(id: params[:hotel_access])
    if @user_to_update.hotels.destroy_all
      if @user_to_update.hotels << @hotels
        if @user_to_update.update(user_params)
          render json: {message: "User successfully updated"}
        else
          render_error("db")
        end
      else
        render("db")
      end
    else
      render_error("db")
    end
  end
  def set_user
    @user = User.find(params[:id])
  end
  def set_account
    if params[:account_id]
      @account = Account.find(params[:account_id])
    elsif params[:user][:account_id]
      @account = Account.find(params[:user][:account_id])
    end
  end
  def user_params
    params.require(:user).permit(
      :email,
      :account_id,
      :first_name,
      :last_name,
      :telephone,
      :position,
      :status,
      :user_id
    )
  end
  def render_error(error_type)
    case error_type
      when "not_admin"
         render json: {error: "You are not allowed to create a user for this account"}
      when "mail_exists"
         render json: {error: "Please fill the email field and try again"}
      when "empty_email"
        render json: {error: "Please fill the email field and try again"}
      when "mail_processing"
         render json: { error: "We couldnt send an email to your invitee. Please try again" }
      when "db"
        render json: {error: "An error occured. Please try again"}
      when "unauthorized"
        render json: {error: "Unauthorized"}
      else
        render json: { errors: @user.errors.full_messages }, status: :unprocessable_entity
    end
  end
  def render_success(success_type)
    case success_type
      when "mail_sent"
        render json: { success: "An email was sent to your collaborator asking him to join your Quickbed team." }
      when "password_changed"
        render json: {success: "Your password was successfully changed"}
      when "updated"
        render json: {success: "Your infos were successfully updated"}
    end
  end
end

关联/users_controller.rb

class Api::V1::Association::UsersController < Api::V1::BaseController
  skip_after_action :verify_authorized, only: [:invite, :update_specific, :show]
  before_action :set_user, except: [:invite, :index, :update_specific]
  before_action :set_account_asso, only: [:index, :show, :invite]
  # creates user linked to account / only account owner can create users linked to account
  # input account_id & email
  def invite
    unless current_user.id != @account_asso.admin_user_id
      user_already_exists_or_email_blank?
      set_new_user
      ActiveRecord::Base.transaction do
        set_offices_access
        save_user_and_send_invitation_email
      end
    else
      render_error("not_admin")
    end
  end
  def show
    if ((current_user == @user) || (@account_asso.admin == current_user))
    else
      render_error("unauthorized")
    end
  end
  # admin can update employee or manager
  def update_specific
    @user_to_update = User.find(params[:id])
    if @user_to_update.account != current_user.created_account
      render_error("unauthorized")
    else
      ActiveRecord::Base.transaction do
        update_user_and_offices_access
      end
    end
  end
  # update self
  def update
    authorize @user
    if @user.update(user_params)
      render_success("updated")
    else
      render_error("db")
    end
  end
  def destroy
    authorize @user
    if @user.destroy
      render json: {message: "User successfully destroyed"}
    else
      render_error("db")
    end
  end
  # envoyer account params
  def index
    if (current_user.created_account_asso == @account_asso) || ((current_user.account_asso == @account_asso) && (current_user.status == "manager"))
      @users = policy_scope(User).where(account_asso: @account_asso)
      @admin = @account_asso.admin
      render json: {users: @users, admin: @admin}
    else
      render_error("unauthorized")
    end
  end
  # unlincks user from account
  #input user_id
  def unlinck
    authorize @user
    @user.account_asso = nil
    if @user.save && @user.offices.delete_all.nil?
      render json: {user: @user}
    else
      render_error("db")
    end
  end
  private
  def user_already_exists_or_email_blank?
    if User.find_by_email(params[:user][:email])
      render_error("mail_exists") and return
    elsif params[:user][:email].blank?
      render_error("empty_email") and return
    end
  end
  def set_new_user
    password = SecureRandom.hex
    invitation_token = SecureRandom.uuid
    @user = User.new(first_name: params[:user][:first_name], last_name: params[:user][:last_name], telephone: params[:user][:telephone], account_asso_id: params[:user][:account_asso_id], email: params[:user][:email], status: params[:user][:status], password: password, password_confirmation: password, invitation_token: invitation_token, invitation_created_at: Time.now, role: "asso")
  end
  def set_offices_access
    if params[:office_access].first == "all"
      @offices = account_asso.offices
    else
      @offices = Office.where(id: params[:office_access])
    end
  end
  def save_user_and_send_invitation_email
    if @user.save &&  @user.offices << offices
      if UserMailer.send_invitation(@user, params[:app_base_url]).deliver_now
        @user.invitation_sent_at = Time.now
        if @user.save
          render_success("mail_sent")
        else
          render_error("db")
        end
      else
        render_error("mail_processing")
      end
    else
      render_error("db")
    end
  end
  def update_user_and_offices_access
   @offices = Office.where(id: params[:office_access])
    if @user_to_update.offices.destroy_all
      if @user_to_update.offices << @offices
        if @user_to_update.update(user_params)
          render json: {message: "User successfully updated"}
        else
          render_error("db")
        end
      else
        render("db")
      end
    else
      render_error("db")
    end
  end
  def set_user
    @user = User.find(params[:id])
  end
  def set_account_asso
    if params[:account_asso_id]
      @account_asso = AccountAsso.find(params[:account_asso_id])
    elsif params[:user][:account_asso_id]
      @account_asso = AccountAsso.find(params[:user][:account_asso_id])
    end
  end
  def user_params
    params.require(:user).permit(
      :email,
      :account_id,
      :first_name,
      :last_name,
      :telephone,
      :position,
      :status,
      :user_id
    )
  end
  def render_error(error_type)
    case error_type
      when "not_admin"
         render json: {error: "You are not allowed to create a user for this account"}
      when "mail_exists"
         render json: {error: "Please fill the email field and try again"}
      when "empty_email"
        render json: {error: "Please fill the email field and try again"}
      when "mail_processing"
         render json: { error: "We couldnt send an email to your invitee. Please try again" }
      when "db"
        render json: {error: "An error occured. Please try again"}
      when "unauthorized"
        render json: {error: "Unauthorized"}
      else
        render json: { errors: @user.errors.full_messages }, status: :unprocessable_entity
    end
  end
  def render_success(success_type)
    case success_type
      when "mail_sent"
        render json: { success: "An email was sent to your collaborator asking him to join your Quickbed team." }
      when "password_changed"
        render json: {success: "Your password was successfully changed"}
      when "updated"
        render json: {success: "Your infos were successfully updated"}
    end
  end
end

也许我应该重写与酒店概念链接的usersController,或者我应该创建第三个superusersController,链接到酒店概念的usersController和链接到协会概念的usersController都将从中继承?你能帮我找到最适合我情况的吗?

您可以查看服务对象。它们只是普通的老Ruby对象。您可以将invite方法提取到类似UsersService#invite的东西中,然后从两个控制器调用它。逻辑上的差异可以通过向其传递一个参数来处理,该参数在中运行(用户或关联)

最新更新