Ich habe eine Rails App mit zwei Controllern, die sehr ähnliche Verhaltensweisen haben. Ein ist ein Userscontroller auf das Konzept von Hotel bezogen, der andere ist auch Userscontroller genannt, aber auf das Konzept der Vereinigung im Zusammenhang, so dass es in einem Ordner Verein gespeichert: class Api::V1::Association::UsersController < Api::V1::BaseController
Verwenden Vererbung für sehr ähnliche Controller in Schienen App
Diese Controller haben sehr ähnliche Verhaltensweisen, Verfahren mit geringfügigem Unterschiede (sie beruhen auf verschiedenen Datenbanktabellen für bestimmte Variablen ...). Ich las über Vererbung und dachte, dass es interessant sein könnte, die Association::UsersController
von der UsersController
zu erben. Denkst du, das könnte in meinem Fall das Richtige sein? Zum Beispiel habe ich versucht, die Methodeneinladung von Association::UsersController
zu vererben, um Vererbung zu verwenden, aber ich bin ein bisschen verwirrt, wie man es macht. Können Sie mir sagen, wie Sie diese Methode umschreiben würden, wenn die Association::UsersController
von der usersController
erbt. Hier ist, wie beide Controller wie folgt aussehen:
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
Verband/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
Vielleicht sollte ich das usersController
dem Konzept von Hotel verbunden rewritte oder vielleicht sollte ich ein drittes superusersController
erstellen, von dem sowohl der userController, der mit dem Konzept des Hotels verknüpft ist, als auch der usersController, der mit dem Assoziationskonzept verknüpft ist, erben würde? Können Sie mir helfen, die beste Lösung für meine Situation zu finden?
Ich würde mich darauf konzentrieren, zuerst den Controller-Code zu beheben; Diese Methoden sind * weit * zu verschachtelt und fast unmöglich zu verstehen. * Dann * sehen, ob es ein gemeinsames Verhalten gibt, * dann * bestimmen * wie * dieses Verhalten zu teilen. –
Ja, es gibt eine Menge nutzloser Duplizierung zwischen diesen beiden Controllern. Das heißt, ich bin mir nicht sicher, ob das Problem so groß ist, dass es sich um Ihr Datenmodell handelt oder wie Sie darüber nachdenken. Der "beste" Weg, um fortzufahren, geht wahrscheinlich über das Auslügen von Dumme-Verhalten in eine Super-Klasse hinaus, aber es ist sicherlich ein Ort, um anzufangen. Aber trotzdem: Dieser Code ist ziemlich schwer zu lesen. –
danke @DaveNewton, ich folge deinem Rat und beginne, einige Code in Methoden zu extrahieren –