如果在Rails 6中不存在嵌套形式的对象,该如何创建?

问题描述

我需要创建一个Training,然后在Rails 6应用程序中添加带有嵌套表单字段(茧)的Attendances。情况如下:

模型如下:

培训模式

class Training < ApplicationRecord  
  has_many :attendances,dependent: :destroy
  has_many :people,through: :attendances
  accepts_nested_attributes_for :attendances,reject_if: :all_blank,allow_destroy: true
end

出勤模式

class Attendance < ApplicationRecord
  belongs_to :training
  belongs_to :person
end

人员模型

class Person < ApplicationRecord
  has_many :attendances,dependent: :destroy
  has_many :trainings,through: :attendances
end

如果数据库中存在Person,则用户从下拉选择字段中选择人员的姓名。

如果Person不存在,则用户必须通过输入人员的姓名和年龄来手动输入人员的信息。

我如何设置控制器和表格以允许用户手动输入人员的姓名和年龄,然后在保存培训后在嵌套的表格字段中自动创建该人员和出勤? strong>

解决方法

键的嵌套属性有一个id字段。 Rails的行为是如果存在id则更新现有记录,或者如果id为空白则创建新记录。

基本上,这就是您需要做的。输入此人的姓名和年龄,但id为空,将创建一个新记录。

我强烈建议您使用cocoon宝石https://github.com/nathanvda/cocoon,它会为您的培训表格提供link_to_add_association的帮助者,它可以自动让您打开一个新的空人表格。实施后,您将使用类似这样的方法来调用帮助程序

<%= link_to_add_association 'add attendee',f,:people %>

您可以忽略通过联接表将人员与培训相关联...在保存新人员时,rails会自动创建联接记录。

,

我使用了上面评论中的链接:https://github.com/nathanvda/cocoon/wiki/A-guide-to-doing-nested-model-forms#the-look-up-or-create-belongs_to

我使用了Wiki中的最后一个示例。

这是我针对该功能的最终MVC版本的结果:

模型

class Person < ApplicationRecord
  has_many :attendances,dependent: :destroy
  has_many :trainings,through: :attendances
end

class Attendance < ApplicationRecord
  belongs_to :training
  belongs_to :person
  accepts_nested_attributes_for :person,:reject_if => :all_blank
end

class Training < ApplicationRecord  
  has_many :attendances
  has_many :people,through: :attendances
  accepts_nested_attributes_for :attendances,reject_if: :all_blank,allow_destroy: true
  accepts_nested_attributes_for :people
end

培训负责人

class TrainingsController < ApplicationController
    
    put your normal controller actions here and then in 
    training_params put this:

    def training_params
      params.require(:training).permit(
        attendances_attributes: [:id,:_destroy,:person_id,person_attributes: [:id,:name,:age,:program_id]]
      )
    end
end

将其添加到培训/表单

  .row
    .col.s12
      .pt-5
        %h6
          Attendance
      #people
        = f.fields_for :attendances do |attendance|
          = render 'attendance_fields',:f => attendance
        .people_links
          = link_to_add_association 'Add',:attendances

将此添加到trainings / _attendance_fields

.nested-fields.attendance-person-fields
  .field
     .person_from_list
       = f.select(:person_id,Person.all.map { |p| [p.name,p.id] },{ include_blank: true },{ :class => 'chosen-select' })
     = link_to_add_association 'Or create',:person,data: {disable_with: "creating person"}

最后在培训中/ _person_fields

.nested-fields
  .input-field
    = f.text_field :name
    = f.label :name
  .input-field
    = f.number_field :age
    = f.label :age

我添加了咖啡脚本:( in:person.coffee

  $('#people').on('cocoon:before-insert',(e,attendance_to_be_added) ->
    attendance_to_be_added.fadeIn 'slow'
    return
  )

  $('#people a.add_fields').data('association-insertion-position','before').data 'association-insertion-node','this'
  
  $('#people').on 'cocoon:after-insert',->
    
    $('.attendance-person-fields a.add_fields').data('association-insertion-position','this'
    
    $('.attendance-person-fields').on 'cocoon:after-insert',->
      
      $(this).children('.person_from_list').remove()
      $(this).children('a.add_fields').hide()

      return
    return

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...