我有一个rails应用程序,它有两个行为非常相似的控制器。一个是与酒店概念相关的UsersController,另一个也被命名为UsersCoontroller,但与关联概念相关,因此它存储在文件夹关联中:class Api::V1::Association::UsersController < Api::V1::BaseController
这些控制器有非常相似的行为,方法略有不同(它们对某些变量依赖于不同的数据库表…)。我读过关于继承的文章,认为让Association::UsersController
从UsersController
继承可能很有趣。你认为这对我来说是正确的做法吗?例如,我一直试图重写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
的东西中,然后从两个控制器调用它。逻辑上的差异可以通过向其传递一个参数来处理,该参数在中运行(用户或关联)