Rails 4 嵌套形式 - 嵌套模型不保存
Rails 4 nested form - nested models not saving
我正准备放弃这个...我已经搜索了所有关于这个的问题,做了多次测试,但我无法弄明白。
我正在尝试通过嵌套属性(教室 -> 学生)创建模型(缺勤)的新记录。
这是我手动创建并在调用
时保存的散列
# hash: {"classroom"=>{"rank"=>"aaa", "grade_id"=>"", "students_attributes"=>{"0"=>{"last_name"=>"aaa", "first_name"=>"aaa", "absences_attributes"=>{"0"=>{"class_time"=>"1", "status"=>"valid"}}}}}, "id"=>"26"}
@classroom = Classroom.find(params["id"])
@classroom.update(params["classroom"])
这给了我:
(0.5ms) begin transaction
SQL (1.3ms) UPDATE "classrooms" SET "rank" = ?, "updated_at" = ? WHERE "classrooms"."id" = ? [["rank", "aaa"], ["updated_at", "2016-08-10 21:09:17.883875"], ["id", 26]]
SQL (0.2ms) INSERT INTO "students" ("last_name", "first_name", "classroom_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["last_name", "aaa"], ["first_name", "aaa"], ["classroom_id", 26], ["created_at", "2016-08-10 21:09:17.897997"], ["updated_at", "2016-08-10 21:09:17.897997"]]
SQL (0.2ms) INSERT INTO "absences" ("class_time", "status", "student_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["class_time", 1], ["status", "Αδικαιολόγητη"], ["student_id", 51], ["created_at", "2016-08-10 21:09:17.902018"], ["updated_at", "2016-08-10 21:09:17.902018"]]
(11.4ms) commit transaction
=> true
然而
当我通过表单提交获得此哈希时,更新不会发生,也不会创建 "absences"。控制台如下所示:
Processing by ClassroomsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"blabla",
"classroom"=>{"students_attributes"=>{"0"=>{"absences_attributes"=>{
"0"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"1", "status"=>"valid"},
"1"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"2", "status"=>"valid"},
"2"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"3", "status"=>"valid"},
"3"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"4", "status"=>"valid"},
"4"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"5", "status"=>"valid"},
"5"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"6", "status"=>"valid"},
"6"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"7", "status"=>"valid"}},
"id"=>"50"}}}, "id"=>"27"}
Classroom Load (0.2ms) SELECT "classrooms".* FROM "classrooms" WHERE "classrooms"."id" = ? LIMIT 1 [["id", 27]]
(0.1ms) begin transaction Student Load
(0.3ms) SELECT "students".* FROM "students" WHERE "students"."classroom_id" = ? AND "students"."id" = 50 [["classroom_id", 27]]
(0.1ms) commit transaction
这是我的教室控制器
class ClassroomsController < ApplicationController
def new
@classroom = Classroom.new
@students = 30.times {@classroom.students.build}
end
def create
@classroom = Classroom.new(classroom_params)
if @classroom.save
redirect_to @classroom
else
flash.now[:danger] = "Try again."
render "new"
end
end
def show
@classroom = Classroom.find(params[:id])
end
def data
@classroom = Classroom.find(params[:id])
@classroom.students.each { |student| 7.times { student.absences.build } }
end
def update
@classroom = Classroom.find(params[:id])
@classroom.update_attributes(classroom_params)
redirect_to @classroom
end
private
def classroom_params
params.require(:classroom).permit(:id, :grade_id, :rank, students_attributes:
[:id, :classroom_id, :first_name, :last_name, absences_attributes:
[:id, :student_id, :date, :status, :class_time]])
end
end
课堂模型
class Classroom < ActiveRecord::Base
# belongs_to :grade
has_many :students, inverse_of: :classroom, dependent: :destroy
accepts_nested_attributes_for :students, allow_destroy: true,
reject_if: proc { |a| [a[:first_name], a[:last_name]].any? {|b| b.blank?}}
has_many :absences, through: :students
accepts_nested_attributes_for :absences, allow_destroy: true,
reject_if: proc { |a| a[:status].blank? }
validates :rank, presence: true
end
学生模型
class Student < ActiveRecord::Base
belongs_to :classroom, inverse_of: :students
has_many :absences, inverse_of: :student
accepts_nested_attributes_for :absences, allow_destroy: true,
reject_if: proc { |a| a[:status].blank? }
# validates :first_name, presence: true
# validates :last_name, presence: true
def full_name
return last_name + " " + first_name
end
end
缺席模型
class Absence < ActiveRecord::Base
belongs_to :student, inverse_of: :absences
# validates :date, presence: true
# validates :class_time, presence: true
# validates :status, presence: true, inclusion: { in: ["valid",
# "invalid", "erased"] }
end
我已关闭所有验证,以确保这不是它们未被保存的原因。
嵌套表单视图
<div id="absences" class="tab-pane fade in active">
<h3>Absences</h3>
<br>
<div class="input-group date col-md-3" id="datepicker">
<input type="text" class="form-control">
<div class="input-group-addon">
<span class="glyphicon glyphicon-th"></span>
</div>
</div>
<%= form_for @classroom do |class_f| %>
<% @classroom.students.each do |student| %>
<div class="student_<%= student.id %>">
<h4><%= student.full_name %></h4>
<div class="absences">
<p>
<% 7.times do |i| %>
<span><%= i + 1 %></span>
<% end %>
</p>
<%= class_f.fields_for :students, student do |student_f| %>
<% student.absences.each_with_index do |absence, i| %>
<div class="school-hour text-center" data-value="<%= i + 1 %>">
<%= fa_icon "plus" %>
<%= fa_stacked_icon "plus", base: "circle-o" %>
<%= fa_icon "minus" %>
<%= student_f.fields_for :absences, absence do |ab_f| %>
<%= ab_f.hidden_field :student_id, value: absence.student_id %>
<%= ab_f.hidden_field :date, class:"input-absence-date" %>
<%= ab_f.hidden_field :class_time, value: i + 1 %>
<%= ab_f.hidden_field :status, class:"input-absence-status" %>
<% end %>
</div>
<% end %>
<% end %>
</div>
</div>
<% end %>
<div class="actions">
<%= button_to "Submit", "#", class:"btn btn-primary"%>
</div>
<% end %>
</div>
没有值的隐藏字段在提交表单之前通过 javascript 填充。我认为这与问题无关。 params hash 通过了,但是没有保存。
没有花很多时间看这个,这可能是问题所在吗?
reject_if: proc { |a| a[:status].blank? }
似乎参数传递的状态为 ""
,.blank?
评估为 true
。
无论您的表单传入什么,在您的第一个示例中您都有 "status"=>"valid"
但在您的第二个示例中来自表单 "status"=>""
我发现问题出在教室模型上的 reject_if。
我试图通过 user
更新 absence
,我实际上并没有更改 user
的名称,因此没有将其作为参数传递。结果记录没有通过 reject_if: proc { |a| [a[:first_name], a[:last_name]].any? {|b| b.blank?}}
所以它根本没有达到缺席记录。我试着放一个 :new_record? reject if 中的验证以及其他检查,但没有成功。
我在这个答案中找到了解决方案:
很棒而且干净。也看看评论
我正准备放弃这个...我已经搜索了所有关于这个的问题,做了多次测试,但我无法弄明白。
我正在尝试通过嵌套属性(教室 -> 学生)创建模型(缺勤)的新记录。
这是我手动创建并在调用
时保存的散列# hash: {"classroom"=>{"rank"=>"aaa", "grade_id"=>"", "students_attributes"=>{"0"=>{"last_name"=>"aaa", "first_name"=>"aaa", "absences_attributes"=>{"0"=>{"class_time"=>"1", "status"=>"valid"}}}}}, "id"=>"26"}
@classroom = Classroom.find(params["id"])
@classroom.update(params["classroom"])
这给了我:
(0.5ms) begin transaction
SQL (1.3ms) UPDATE "classrooms" SET "rank" = ?, "updated_at" = ? WHERE "classrooms"."id" = ? [["rank", "aaa"], ["updated_at", "2016-08-10 21:09:17.883875"], ["id", 26]]
SQL (0.2ms) INSERT INTO "students" ("last_name", "first_name", "classroom_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["last_name", "aaa"], ["first_name", "aaa"], ["classroom_id", 26], ["created_at", "2016-08-10 21:09:17.897997"], ["updated_at", "2016-08-10 21:09:17.897997"]]
SQL (0.2ms) INSERT INTO "absences" ("class_time", "status", "student_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["class_time", 1], ["status", "Αδικαιολόγητη"], ["student_id", 51], ["created_at", "2016-08-10 21:09:17.902018"], ["updated_at", "2016-08-10 21:09:17.902018"]]
(11.4ms) commit transaction
=> true
然而
当我通过表单提交获得此哈希时,更新不会发生,也不会创建 "absences"。控制台如下所示:
Processing by ClassroomsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"blabla",
"classroom"=>{"students_attributes"=>{"0"=>{"absences_attributes"=>{
"0"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"1", "status"=>"valid"},
"1"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"2", "status"=>"valid"},
"2"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"3", "status"=>"valid"},
"3"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"4", "status"=>"valid"},
"4"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"5", "status"=>"valid"},
"5"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"6", "status"=>"valid"},
"6"=>{"student_id"=>"50", "date"=>"2016/08/17", "class_time"=>"7", "status"=>"valid"}},
"id"=>"50"}}}, "id"=>"27"}
Classroom Load (0.2ms) SELECT "classrooms".* FROM "classrooms" WHERE "classrooms"."id" = ? LIMIT 1 [["id", 27]]
(0.1ms) begin transaction Student Load
(0.3ms) SELECT "students".* FROM "students" WHERE "students"."classroom_id" = ? AND "students"."id" = 50 [["classroom_id", 27]]
(0.1ms) commit transaction
这是我的教室控制器
class ClassroomsController < ApplicationController
def new
@classroom = Classroom.new
@students = 30.times {@classroom.students.build}
end
def create
@classroom = Classroom.new(classroom_params)
if @classroom.save
redirect_to @classroom
else
flash.now[:danger] = "Try again."
render "new"
end
end
def show
@classroom = Classroom.find(params[:id])
end
def data
@classroom = Classroom.find(params[:id])
@classroom.students.each { |student| 7.times { student.absences.build } }
end
def update
@classroom = Classroom.find(params[:id])
@classroom.update_attributes(classroom_params)
redirect_to @classroom
end
private
def classroom_params
params.require(:classroom).permit(:id, :grade_id, :rank, students_attributes:
[:id, :classroom_id, :first_name, :last_name, absences_attributes:
[:id, :student_id, :date, :status, :class_time]])
end
end
课堂模型
class Classroom < ActiveRecord::Base
# belongs_to :grade
has_many :students, inverse_of: :classroom, dependent: :destroy
accepts_nested_attributes_for :students, allow_destroy: true,
reject_if: proc { |a| [a[:first_name], a[:last_name]].any? {|b| b.blank?}}
has_many :absences, through: :students
accepts_nested_attributes_for :absences, allow_destroy: true,
reject_if: proc { |a| a[:status].blank? }
validates :rank, presence: true
end
学生模型
class Student < ActiveRecord::Base
belongs_to :classroom, inverse_of: :students
has_many :absences, inverse_of: :student
accepts_nested_attributes_for :absences, allow_destroy: true,
reject_if: proc { |a| a[:status].blank? }
# validates :first_name, presence: true
# validates :last_name, presence: true
def full_name
return last_name + " " + first_name
end
end
缺席模型
class Absence < ActiveRecord::Base
belongs_to :student, inverse_of: :absences
# validates :date, presence: true
# validates :class_time, presence: true
# validates :status, presence: true, inclusion: { in: ["valid",
# "invalid", "erased"] }
end
我已关闭所有验证,以确保这不是它们未被保存的原因。
嵌套表单视图
<div id="absences" class="tab-pane fade in active">
<h3>Absences</h3>
<br>
<div class="input-group date col-md-3" id="datepicker">
<input type="text" class="form-control">
<div class="input-group-addon">
<span class="glyphicon glyphicon-th"></span>
</div>
</div>
<%= form_for @classroom do |class_f| %>
<% @classroom.students.each do |student| %>
<div class="student_<%= student.id %>">
<h4><%= student.full_name %></h4>
<div class="absences">
<p>
<% 7.times do |i| %>
<span><%= i + 1 %></span>
<% end %>
</p>
<%= class_f.fields_for :students, student do |student_f| %>
<% student.absences.each_with_index do |absence, i| %>
<div class="school-hour text-center" data-value="<%= i + 1 %>">
<%= fa_icon "plus" %>
<%= fa_stacked_icon "plus", base: "circle-o" %>
<%= fa_icon "minus" %>
<%= student_f.fields_for :absences, absence do |ab_f| %>
<%= ab_f.hidden_field :student_id, value: absence.student_id %>
<%= ab_f.hidden_field :date, class:"input-absence-date" %>
<%= ab_f.hidden_field :class_time, value: i + 1 %>
<%= ab_f.hidden_field :status, class:"input-absence-status" %>
<% end %>
</div>
<% end %>
<% end %>
</div>
</div>
<% end %>
<div class="actions">
<%= button_to "Submit", "#", class:"btn btn-primary"%>
</div>
<% end %>
</div>
没有值的隐藏字段在提交表单之前通过 javascript 填充。我认为这与问题无关。 params hash 通过了,但是没有保存。
没有花很多时间看这个,这可能是问题所在吗?
reject_if: proc { |a| a[:status].blank? }
似乎参数传递的状态为 ""
,.blank?
评估为 true
。
无论您的表单传入什么,在您的第一个示例中您都有 "status"=>"valid"
但在您的第二个示例中来自表单 "status"=>""
我发现问题出在教室模型上的 reject_if。
我试图通过 user
更新 absence
,我实际上并没有更改 user
的名称,因此没有将其作为参数传递。结果记录没有通过 reject_if: proc { |a| [a[:first_name], a[:last_name]].any? {|b| b.blank?}}
所以它根本没有达到缺席记录。我试着放一个 :new_record? reject if 中的验证以及其他检查,但没有成功。
我在这个答案中找到了解决方案: 很棒而且干净。也看看评论