【问题标题】:Rails 4 nested form - nested models not savingRails 4嵌套形式 - 嵌套模型不保存
【发布时间】:2016-08-10 21:54:50
【问题描述】:

我正准备放弃这个...我已经搜索了所有关于这个的问题,做了多次测试,但我无法弄清楚。

我正在尝试通过嵌套属性(教室 -> 学生)创建模型(缺勤)的新记录。

这是我手动创建并在调用时保存的哈希

# 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 

但是

当我通过表单提交获得此哈希时,不会发生更新,也不会创建“缺席”。下面是控制台的样子:

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 填充。我不认为这与问题有关。参数散列通过,但缺席并没有保存。

【问题讨论】:

    标签: ruby-on-rails-4 nested-forms nested-attributes params


    【解决方案1】:

    没有花很多时间看这个,这可能是问题吗?

    reject_if: proc { |a| a[:status].blank? }
    

    似乎参数传递的状态为"".blank? 的计算结果为true

    无论您的表单传入什么,在您的第一个示例中您有 "status"=&gt;"valid",但在您的第二个示例中来自表单 "status"=&gt;""

    【讨论】:

    • 对不起,我之前放错了哈希值。我用一个完全填充的哈希编辑了我的答案。换句话说,即使状态不是空白,缺勤仍然没有保存。
    • 经过一番挫折后,我几乎意外地发现问题出在教室模型上的 reject_if 问题。因为我是通过用户更新缺席,所以我实际上并没有更改用户的名称,因此没有将其作为参数传递。结果,该记录没有通过reject_if 名称空白,因此它根本没有达到缺勤记录。感谢您的输入! :)
    • 好的,问题解决了吗?对我的回答不赞成?不管怎样,很高兴你修好了。
    • 你去。再次感谢您的输入。 :)
    • 干得好!我是否可以建议您发布自己的答案,以防其他人发现它有帮助。如果您更新了您的问题,它可能混淆了问题的原因,因为您的原始帖子在参数中显示 "status"=&gt;""
    【解决方案2】:

    我发现问题出在课堂模型上的 reject_if。

    我试图通过user 更新absence,我实际上并没有更改user 的名称,因此没有将其作为参数传递。结果记录没有通过reject_if: proc { |a| [a[:first_name], a[:last_name]].any? {|b| b.blank?}},所以它根本没有达到缺勤记录。我试着放一个 :new_record?如果与其他检查一起在拒绝中进行验证,但这没有成功。

    我在这个答案中找到了解决方案:https://stackoverflow.com/a/13774269/5909738 很棒很干净。看看 cmets 也是如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多