ruby on rails - formularios - Rails 4 atributos anidados y has_many: a través de la asociación en una forma
formularios en rails (1)
Al emplear una relación has_many :through
, debe pasar los nested_attributes
través de los diferentes modelos, como este:
Modelos
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
Controlador
#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
Formar
#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 %>
Aprecio que esto no sea exactamente lo que estás buscando, pero no leí toda tu prosa. Acabo de nested_attributes
que necesitabas ayuda para pasar los nested_attributes
través de una relación has_many :through
Tengo un problema al gestionar un has_many: a través de una asociación que utiliza un formulario. Lo que NO quiero hacer es editar los atributos del modelo asociado de los que hay una gran cantidad de información, más bien, quiero administrar la asociación ÚNICAMENTE. Entiendo que podría hacer esto manipulando los parámetros de formulario pasados a mi acción y construir las relaciones manualmente, pero preferiría seguir el camino de Rieles, si eso es posible.
Una cosa interesante de mi caso es que este has_many: a través de la asociación está en realidad en un modelo que ya estoy guardando usando accepts_nested_attributes_for
Aquí están mis modelos: Metas, Hitos y Programas.
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
Ahora, en mi vista de edición de objetivos, necesito poder agregar y quitar hitos, y para esos hitos necesito poder agregar y eliminar asociaciones de programas. Este es el código de mi formulario.
<%= 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 %>
En mi controlador, tengo
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
Este formulario debe ser como una hoja de trabajo donde puede realizar cambios y solo guardar los cambios una vez que haga clic en guardar al final, por lo que no creo que las gemas como cocoon o nestted_forms ayuden.
Mi código funciona perfectamente hasta ahora para administrar mis objetivos asociados a los objetivos y sus atributos. Pero ahora quiero poder administrar la lista de Programas asociados a esos Hitos.
He intentado usar accepts_nested_attributes_for pero eso no es exactamente lo que quiero porque no me importa editar los atributos anidados del modelo, los atributos del programa deben permanecer estáticos.
Pensé que podría tener algo como esto en mi formulario para cada programa para construir las asociaciones:
<input type="hidden" name="goal[milestones_attributes][1][program_ids][1]" >
Pero eso tampoco funciona (por supuesto que he agregado: program_ids a mis parámetros listados en blanco). ¿Hay algún método de rieles mágicos que deba agregar a mi controlador?
¿Que me estoy perdiendo aqui?
¡Gracias por adelantado!