フォームを使用したhas_many:throughアソシエーションの管理に問題があります。私がしたくないことは、そこに大量の情報が存在する関連モデルの属性を編集することではなく、関連付けのみを管理したいことです。私は自分のアクションに渡されるフォームパラメータを操作することでこれを行うことができ、リレーションシップを手動で構築できることを理解していますが、可能であればRailsの方法を選びます。
私の場合の興味深い点は、このhas_many:through関連付けが、accepts_nested_attributes_forを使用して既に保存しているモデル上に実際にあるということです。
私のモデルは次のとおりです。目標、マイルストーン、プログラム。
class Goal < ActiveRecord::Base
has_many :milestones, inverse_of: :goal, dependent: :destroy
accepts_nested_attributes_for :milestones, :allow_destroy => true
end
class Milestone < ActiveRecord::Base
belongs_to :goal, inverse_of: :milestones
has_many :milestone_programs
has_many :programs, :through => :milestone_programs
end
class Program < ActiveRecord::Base
end
目標編集ビューで、マイルストーンを追加および削除できるようにする必要があります。これらのマイルストーンについては、プログラムの関連付けを追加および削除できるようにする必要があります。これは私のフォームのコードです。
<%= form_for @goal do |f| %>
<%= f.fields_for :milestones do |f_milestone| %>
<%= f.hidden_field :id, :value => f.object.id %>
<%= f.hidden_field :name, :value => f.object.name %>
<a href="javascript:void(0)" class="milestone-remove">- remove</a>
<ul>
<%= f.fields_for :programs do |f_prog| %>
<li>
<%= f_prog.object.name %>
<a href="javascript:void(0)" class="program-remove">- remove</a>
</li>
<% end %>
</ul>
<% end %>
<%= f.submit 'Save' %>
<% end %>
私のコントローラーには、
class GoalsController < ApplicationController
# PATCH/PUT /goals/:id
def update
if @goal.update(goal_params)
redirect_to @goal
end
end
def goal_params
params.require(:goal).permit(:name, :milestones_attributes => [ :id, :name, :_destroy ])
end
end
このフォームはワークシートのようなものである必要があり、変更を加えて最後に[保存]をクリックした後にのみ変更を保存できるため、cocoonやnested_formsなどのgemが役立つとは思いません。
これまでの私のコードは、マイルストーンとその属性に関連する目標を管理するために完全に機能します。しかし、今、それらのマイルストーンに関連付けられているプログラムのリストを管理できるようにしたいと考えています。
Accepts_nested_attributes_forを使用してみましたが、モデルのネストされた属性を編集する必要がないため、プログラムの属性は静的なままであるため、それは正確には必要ではありません。
各プログラムが関連付けを作成するために、フォームに次のようなものを含めることができると考えました。
<input type="hidden" name="goal[milestones_attributes][1][program_ids][1]" >
しかし、それでも機能しません(もちろん、ホワイトリストに登録されたパラメーターに:program_idsを追加しました)。コントローラーに追加する必要がある魔法Rails=メソッドはありますか?
ここに何が欠けていますか?
前もって感謝します!
has_many :through
関係を使用する場合、次のように、異なるモデルにnested_attributes
を渡す必要があります。
モデル
class Goal < ActiveRecord::Base
has_many :milestones, inverse_of: :goal, dependent: :destroy
accepts_nested_attributes_for :milestones, :allow_destroy => true
def self.build
goal = self.new
goal.milestones.build.milestone_programs.build_program
end
end
class Milestone < ActiveRecord::Base
belongs_to :goal, inverse_of: :milestones
has_many :milestone_programs
has_many :programs, through: :milestone_programs
accepts_nested_attributes_for :milestone_programs
end
class MilestoneProgram < ActiveRecord::Base
belongs_to :milestone
belongs_to :program
accepts_nested_attributes_for :program
end
class Program
has_many :milestone_programs
has_many :milestones, through: :milestone_programs
end
コントローラー
#app/controllers/goals_controller.rb
def new
@goal = Goal.build
end
def create
@goal = Goal.new(goal_params)
@goal.save
end
private
def goal_params
params.require(:goal).permit(milestones_attributes: [milestone_programs_attributes: [program_attributes:[]]])
end
フォーム
#app/views/goals/new.html.erb
<%= form_for @goal do |f| %>
<%= f.fields_for :milestones do |m| %>
<%= m.fields_for :milestone_programs do |mp| %>
<%= mp.fields_for :program do |p| %>
<%= p.text_field :name %>
<% end %>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
これはあなたが探しているものではないかもしれないことを感謝しますが、すべての散文を読みませんでした。 nested_attributes
関係を通じてhas_many :through
を渡すのに必要な情報を集めました