我目前正在尝试重构一些控制器代码,但遇到了一些我不确定如何以正确方式实现的代码。
我的应用程序有用户和公司,并且都可以有项目。 当前的情况是,我们有2个网址:
那些将路由到同一控制器,该控制器将根据company_id是否存在来不同地处理请求。我认为这不是很干净,因此我一直在考虑一种更好的方法。
到目前为止,我认为最好的方法是将它们分成单独的控制器,例如:
但是,由于用户项目和公司项目之间的唯一区别几乎是一个项目具有一个“ user_id”,另一个项目具有一个“ company_id”,因此感觉就像我将要写的那样不那么干很多重复的代码。
当前的解决方案可能并不是什么大问题,但我想以正确的方式进行操作,因此希望这里的人对如何处理此问题提出建议。
谢谢!
编辑:
这是我的ProjectsController#create当前的外观
def create
if params[:company_id]
company = current_user.get_companies.find(params[:company_id])
@project = Project.new(project_params)
@project.company_id = company.id
else
@project = Project.new(project_params)
@project.user_id = current_user.id
end
@project = Project.new(project_params)
if @project.save
flash[:notice] = "Project '#{@project.name}' created."
if @project.company
redirect_to company_project_path(@project.company, @project)
else
redirect_to project_path(@project)
end
else
flash[:error] = @project.errors.full_messages
if params[:company_id]
redirect_to new_company_project_path(params[:company_id], @project)
else
redirect_to new_project_path(@project)
end
end
end
主要是我想摆脱的if / else逻辑 所以我可能应该只将company_id和user_id添加到allowed_params中,然后使用函数将其中一个放置在params中。
答案 0 :(得分:2)
好的,我设法以自己满意的方式来处理它。 ProjectsController#create现在看起来像这样:
def create
@project = owner.projects.new(project_params)
if @project.save
flash[:notice] = "Project '#{@project.name}' created."
redirect_to action: :show, id: @project.id
else
flash[:error] = @project.errors.full_messages
@project = Project.new(project_params)
render action: :new
end
end
def owner
if params[:company_id]
return policy_scope(Company).find(params[:company_id])
else
return current_user
end
end
我添加了所有者类以返回项目所属的实体。 仍然欢迎任何改进建议!
答案 1 :(得分:2)
由于您说的唯一区别是将company_id
与user_id
关联起来,就像@TomLord所说的那样,您可能会发现以下类似的内容对您有用:
假设您正在使用shallow nested routes:
class ProjectsController < ApplicationController
COLLECTION_ACTIONS = [:index, :new, :create].freeze
MEMBER_ACTIONS = [:show, :edit, :update, :destroy].freeze
before_action :set_associated_record, only: COLLECTION_ACTIONS
before_action :set_project, only: MEMBER_ACTIONS
def index
@projects = @associated_record.projects
# ...
end
def new
@project = @associated_record.projects.new
# ...
end
def create
@project = @associated_record.projects.new(project_params)
# ...
end
private
def set_project
@project = Project.find(params[:id])
end
def set_company
if params[:company_id].present?
@company = Company.find(params[:company_id])
end
end
# you might want to remove this set_user method, because perhaps you are already setting @user from sesssion
def set_user
if params[:user_id].present?
@user = User.find(params[:user_id])
end
end
def set_associated_record
set_company
set_user
@associated_record = @company || @user
end
end