I'm trying to copy the values from Model A nested attributes to Model B nested attributes. The nested fields are the same in their respective tables. Just the parents are different.
I pass the model A value: Model_B_new_path(@routine)
and get its value in controller B: @routine = Routine.find(params[:id])
, but copying the nested attributes is where I'm stuck.
class RoutineSetRep
belongs_to :routine
end
class Routine
has_many :routine_set_reps, dependent: :destroy
accepts_nested_attributes_for :routine_set_reps, allow_destroy: true
validates_associated :routine_set_reps
end
class WorkoutSetRep
belongs_to: :workout
end
class Workout
has_many :workout_set_reps, dependent: :destroy
accepts_nested_attributes_for :workout_set_reps, allow_destroy: true
validates_associated :workout_set_reps
end
Controllers:
Controller Workout / Controller B
def new
@new_routine_workout = Routine.find_by(id: params[:routine_id])
@routine = @new_routine_workout
c = @routine.routine_set_reps.count
@workout = current_user.workouts.new(@routine.attributes.except('public'))
c.times{ @workout.workout_set_reps.build }
end
def workout_params
params.fetch(:workout, {}).permit(:id, :sport_id, :name, :user_id, :routine_id,
workout_set_reps_attributes: [:id, :set, :rep, :weight, :distance, :workout_id, :exercise_id,
:user_id, :weight_unit, :distance_unit, :_destroy],)
end
end
I can make the form build the number of fields that should be populated, but aren't.
Would this be a deep clone problem in which I have to create a method that grabs each routine_set_rep? Something like:
@routine.routine_set_reps.each do |set|
set.exercise_id = @workout.workout_set_reps.exercise_id
end
This does not work but seems to be the right direction. With that said is the idea behind it, is that possible?
When I set the build option to build previous workout records it works fine.
@past_workout = Workout.find_by(id: params[:past_workout_id])
@workout = current_user.workouts.new(@past_workout.attributes.except('public')).copy_workout
The form:
<%= content_tag :div, class: "nested-fields", data: { new_record: form.object.new_record? } do %>
<div class="form-group">
<%= form.hidden_field :_destroy %>
<%= form.collection_select(:exercise_id, Exercise.order(:tool), :id, :name_with_tool, {prompt: nil}, {class: 'form'}) %>
<%= form.text_field :set, placeholder: "Set", class: "set-control" %>
<%= form.text_field :rep, placeholder: "Rep", class: "set-control" %>
<%= form.text_field :weight, placeholder: "Weight", class: "set-control" %>
<%= form.collection_select :weight_unit, WorkoutSetRep::WEIGHT, :to_s, :titleize, {prompt: nil}, {:class => 'set-control'} %>
<%= form.text_field :distance, placeholder: "Distance To Run", class: "set-control" %>
<small><%= link_to "Remove", "#", class: "btn btn--destroy", data: { action: "click->nested-form#remove_association" } %></small>
</div>
<% end %>
I've stumbled onto these post for help,post post post which they have, but I'm still lost.
First I set the variables, then I was able to iterate over them. Is this is the rails way? I don't know but it works and the max number of objects it would iterate over is 20.
@routine = Routine.includes(:routine_set_reps).find_by(id: params[:routine_id])
@workout = current_user.workouts.new(@routine.attributes.extract!('name', 'sport'))
c = r.count
r = @routine.routine_set_reps
w = @workout.workout_set_reps
c.times{ w.new }
r.zip(w).each do |routine, workout|
workout.exercise_id = routine.exercise_id
workout.set = routine.set
workout.rep = routine.rep
workout.weight = routine.weight
workout.weight_unit = routine.weight_unit
end
Probably could refactor this into a method and just call it but for now working is working.
Just fyi I use =
instead of ||=
because the workout_set_reps
will always be new. Is this right? I'm not positive, but leave a comment if you believe differently or agree with a reason.