以单一形式创建第 3 级 child - Rails 5
Create 3rd level child in a single form - Rails 5
我正在 ROR 上构建一个简单的 top-to-bottom 日常锻炼应用程序。我可以在同一个表格上创建锻炼日 (parent) 和锻炼 (child)。但是当我提交表单时,我似乎无法保存加权集(grandchild)。有趣的是,由于保存了锻炼,我可以转到该锻炼编辑页面,添加一个加权集,加权集将显示在锻炼日显示页面中。我认为这与加权集在创建时未与练习相关联有关。如何将三个模型绑定在一起?我知道我很接近!
我全app on github. I the link isn't working, try this URL https://github.com/j-acosta/routine/tree/association
型号
class WorkoutDay < ApplicationRecord
has_many :exercises, dependent: :destroy
has_many :weighted_sets, through: :exercises
accepts_nested_attributes_for :exercises
accepts_nested_attributes_for :weighted_sets
end
class Exercise < ApplicationRecord
belongs_to :workout_day, optional: true
has_many :weighted_sets, dependent: :destroy
accepts_nested_attributes_for :weighted_sets
end
class WeightedSet < ApplicationRecord
belongs_to :exercise, optional: true
end
锻炼日控制器
class WorkoutDaysController < ApplicationController
before_action :set_workout_day, only: [:show, :edit, :update, :destroy]
...
# GET /workout_days/new
def new
@workout_day = WorkoutDay.new
# has_many association .build method => @parent.child.build
@workout_day.exercises.build
# has_many :through association .build method => @parent.through_child.build
# @workout_day.weighted_sets.build
@workout_day.weighted_sets.build
end
...
# POST /workout_days
# POST /workout_days.json
def create
@workout_day = WorkoutDay.new(workout_day_params)
respond_to do |format|
if @workout_day.save
format.html { redirect_to @workout_day, notice: 'Workout day was successfully created.' }
format.json { render :show, status: :created, location: @workout_day }
else
format.html { render :new }
format.json { render json: @workout_day.errors, status: :unprocessable_entity }
end
end
end
...
private
# Use callbacks to share common setup or constraints between actions.
def set_workout_day
@workout_day = WorkoutDay.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def workout_day_params
params.require(:workout_day).permit(:title, exercises_attributes: [:title, :_destroy, weighted_sets_attributes: [:id, :weight, :repetition]])
end
end
新的锻炼日表格
<%= form_for @workout_day do |workout_day_form| %>
<% if workout_day.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(workout_day.errors.count, "error") %> prohibited this workout_day from being saved:</h2>
<ul>
<% workout_day.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= workout_day_form.label :title, 'Workout Day Name' %>
<%= workout_day_form.text_field :title %>
</div>
exercise_field will go here
<div>
<%= workout_day_form.fields_for :exercises do |exercise_field| %>
<%= exercise_field.label :title, 'Exercise' %>
<%= exercise_field.text_field :title %>
<% end %>
</div>
weighted_set_fields will go here
<div>
<%= workout_day_form.fields_for :weighted_sets do |set| %>
<%= render 'exercises/weighted_set_fields', f: set %>
<% end %>
</div>
<div>
<%= workout_day_form.submit %>
</div>
<% end %>
罪魁祸首是workout_day_params
。在表单中,weighted_sets
字段嵌套在 workout_day
下。但是在 workout_day_params
中,您在 exercises_attributes
下有 weighted_sets_attributes
,这就是您遇到问题的原因。将其更改为以下应该可以解决问题。
def workout_day_params
params.require(:workout_day).permit(:title, exercises_attributes: [:title, :_destroy], weighted_sets_attributes: [:id, :weight, :repetition])
end
ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection
这是由于错误的联想。您应该考虑像下面这样调整您的关联
class WorkoutDay < ApplicationRecord
has_many :weighted_sets, dependent: :destroy
has_many :exercises, through: :weighted_sets
accepts_nested_attributes_for :exercises
accepts_nested_attributes_for :weighted_sets
end
class Exercise < ApplicationRecord
has_many :weighted_sets, dependent: :destroy
has_many :workout_days, through: :weighted_sets
end
class WeightedSet < ApplicationRecord
belongs_to :exercise, optional: true
belongs_to :workout_day, optional: true
end
我正在 ROR 上构建一个简单的 top-to-bottom 日常锻炼应用程序。我可以在同一个表格上创建锻炼日 (parent) 和锻炼 (child)。但是当我提交表单时,我似乎无法保存加权集(grandchild)。有趣的是,由于保存了锻炼,我可以转到该锻炼编辑页面,添加一个加权集,加权集将显示在锻炼日显示页面中。我认为这与加权集在创建时未与练习相关联有关。如何将三个模型绑定在一起?我知道我很接近!
我全app on github. I the link isn't working, try this URL https://github.com/j-acosta/routine/tree/association
型号
class WorkoutDay < ApplicationRecord
has_many :exercises, dependent: :destroy
has_many :weighted_sets, through: :exercises
accepts_nested_attributes_for :exercises
accepts_nested_attributes_for :weighted_sets
end
class Exercise < ApplicationRecord
belongs_to :workout_day, optional: true
has_many :weighted_sets, dependent: :destroy
accepts_nested_attributes_for :weighted_sets
end
class WeightedSet < ApplicationRecord
belongs_to :exercise, optional: true
end
锻炼日控制器
class WorkoutDaysController < ApplicationController
before_action :set_workout_day, only: [:show, :edit, :update, :destroy]
...
# GET /workout_days/new
def new
@workout_day = WorkoutDay.new
# has_many association .build method => @parent.child.build
@workout_day.exercises.build
# has_many :through association .build method => @parent.through_child.build
# @workout_day.weighted_sets.build
@workout_day.weighted_sets.build
end
...
# POST /workout_days
# POST /workout_days.json
def create
@workout_day = WorkoutDay.new(workout_day_params)
respond_to do |format|
if @workout_day.save
format.html { redirect_to @workout_day, notice: 'Workout day was successfully created.' }
format.json { render :show, status: :created, location: @workout_day }
else
format.html { render :new }
format.json { render json: @workout_day.errors, status: :unprocessable_entity }
end
end
end
...
private
# Use callbacks to share common setup or constraints between actions.
def set_workout_day
@workout_day = WorkoutDay.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def workout_day_params
params.require(:workout_day).permit(:title, exercises_attributes: [:title, :_destroy, weighted_sets_attributes: [:id, :weight, :repetition]])
end
end
新的锻炼日表格
<%= form_for @workout_day do |workout_day_form| %>
<% if workout_day.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(workout_day.errors.count, "error") %> prohibited this workout_day from being saved:</h2>
<ul>
<% workout_day.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= workout_day_form.label :title, 'Workout Day Name' %>
<%= workout_day_form.text_field :title %>
</div>
exercise_field will go here
<div>
<%= workout_day_form.fields_for :exercises do |exercise_field| %>
<%= exercise_field.label :title, 'Exercise' %>
<%= exercise_field.text_field :title %>
<% end %>
</div>
weighted_set_fields will go here
<div>
<%= workout_day_form.fields_for :weighted_sets do |set| %>
<%= render 'exercises/weighted_set_fields', f: set %>
<% end %>
</div>
<div>
<%= workout_day_form.submit %>
</div>
<% end %>
罪魁祸首是workout_day_params
。在表单中,weighted_sets
字段嵌套在 workout_day
下。但是在 workout_day_params
中,您在 exercises_attributes
下有 weighted_sets_attributes
,这就是您遇到问题的原因。将其更改为以下应该可以解决问题。
def workout_day_params
params.require(:workout_day).permit(:title, exercises_attributes: [:title, :_destroy], weighted_sets_attributes: [:id, :weight, :repetition])
end
ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection
这是由于错误的联想。您应该考虑像下面这样调整您的关联
class WorkoutDay < ApplicationRecord
has_many :weighted_sets, dependent: :destroy
has_many :exercises, through: :weighted_sets
accepts_nested_attributes_for :exercises
accepts_nested_attributes_for :weighted_sets
end
class Exercise < ApplicationRecord
has_many :weighted_sets, dependent: :destroy
has_many :workout_days, through: :weighted_sets
end
class WeightedSet < ApplicationRecord
belongs_to :exercise, optional: true
belongs_to :workout_day, optional: true
end