這是我努力尋找良好解決方案的那些「真實世界項目」問題之一。Rails 4+:具有多個關聯的單個資源,控制器組織
我有一個task
模型與幾種不同的資源相關聯,我需要允許來自每個這些關聯資源的CRUD能力。
例如,一個project
有很多tasks
,我需要更新tasks
在project
的上下文中。
此外,每個project
有許多milestones
,並且每個milestone
也可以有很多tasks
。
這種情況下,task
可能會或可能不會與milestone
相關聯。
class Project < ApplicationRecord
has_many :milestones
has_many :tasks
end
class Milestone < ApplicationRecord
belongs_to :project # required
has_many :tasks
end
class Task < ApplicationRecord
belongs_to :project # required
belongs_to :milestone # optional
end
我有命名空間我的控制器更好的組織和控制。這使我的路線,如:
# routes.rb
resources :projects do
namespace :projects do
resources :milestones # app/controllers/projects/milestones_controller.rb
resources :tasks # app/controllers/projects/tasks_controller.rb
end
end
resources :milestones do
namespace :milestones do
resources :tasks # app/controllers/milestones/tasks_controller.rb
end
end
我也是用了很多AJAX的,使接口快(與Turbolinks),所以我的行動遵循<action>.js.erb
格式,其中使用JavaScript來更新頁面,而不是頁面刷新。請注意,我爲task
表單也使用了對話框/彈出式界面,因此我不能只進行整個頁面刷新。
雖然這個「工作」,它結束了我有很多重複代碼的情況。
# projects/tasks_controller.rb
def new
@project = Project.find(params[:project_id])
@task = @project.tasks.new
end
def create
@project = Project.find(params[:project_id])
@task = @project.tasks.new(task_params)
if @task.save
# create.js.erb
else
render js: "alert('error');" # example...
end
end
# app/views/projects/tasks/create.js.erb
$("#tasks_for_<%= dom_id(@project) %>").append("<%=j render(partial: 'projects/tasks/task') %>");
# milestones/tasks_controller.rb
def new
@milestone = Milestone.find(params[:milestone_id])
@task = @milestone.tasks.new
end
def create
@milestone = Milestone.find(params[:milestone_id])
@task = @milestone.tasks.new(task_params)
if @task.save
# create.js.erb
else
render js: "alert('error');" # example...
end
end
# app/views/milestones/tasks/create.js.erb
$("#tasks_for_<%= dom_id(@milestone) %>").append("<%=j render(partial: 'milestones/tasks/task') %>");
這只是一些示例代碼,來自實際系統的代碼顯示了更多的重複。如您所知,每個不同資源中有很多重複代碼,與tasks
資源的交互稍有不同。
是否有一些標準格式或Rails功能可以幫助構建由其他資源操縱的資源?
我怎樣才能減少這種重複?它直接導致一個複雜的系統,每當我添加或更改某個功能時,我都必須在3個以上的不同地方進行更改。
這正是爲什麼你應該使用演示者,服務,經理等(所有普通的老紅寶石對象)。 – jvillian
@jvillian:我確實使用演示者和服務對象以及其他PORO。但我不確定這些將如何幫助減少上述控制器和視圖的重複?問題在於3個以上的地方使用相同代碼的90%,我不確定如何幹掉代碼,但仍然允許10%的差異。 –