これは私が良い解決策を見つけるのに苦労している "現実世界のプロジェクト"の問題の1つです。Rails 4+:複数のアソシエーションを持つ単一のリソース、コントローラ組織
私はいくつかの異なるリソースに関連付けられたtask
モデルを持っています。これらの関連リソースのそれぞれからCRUD能力を許可する必要があります。
たとえば、project
には多くのtasks
があり、project
の文脈でtasks
を更新する必要があります。
また、それぞれ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
私は、より良い構成と制御のためにコントローラに名前を付けました。私の行動は、私はページを更新する代わりにするためにJavaScriptを使用<action>.js.erb
フォーマットに従ってくださいので、私はまた、インタフェースが高速(Turbolinks付き)にするためにAJAXの多くを使用しています
# 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
:それは、次のようなルートで私をリードページが更新されます。私は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%を使用していることです。コードをDRYする方法はまだわかりませんが、その10%の違いがまだあります。 –