在rails app中为非常相似的控制器使用继承

时间:2016-05-03 12:46:50

标签: ruby-on-rails ruby inheritance

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

这些控制器具有非常相似的行为,方法存在细微差别(它们依赖于某些变量的不同数据库表......)。我正在阅读有关继承的内容,并认为从Association::UsersController继承UsersController可能会很有趣。你认为这可能是我的理由吗?例如,我一直在尝试重写Association::UsersController的方法邀请来使用继承,但我对如何做它有点困惑。如果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链接到概念协会会继承吗?你能帮我找到最合适的情况吗?

1 个答案:

答案 0 :(得分:1)

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