Ruby on rails 如果Rails 6中没有嵌套形式的对象,如何创建该对象?

Ruby on rails 如果Rails 6中没有嵌套形式的对象,如何创建该对象?,ruby-on-rails,nested-forms,cocoon-gem,Ruby On Rails,Nested Forms,Cocoon Gem,我需要创建一个培训,然后在Rails 6应用程序中添加带有嵌套表单字段(cocoon)的出席人数。情况如下: 模型如下: 培训模式 class Training < ApplicationRecord has_many :attendances, dependent: :destroy has_many :people, through: :attendances accepts_nested_attributes_for :attendances, reject_if:

我需要创建一个
培训
,然后在Rails 6应用程序中添加带有嵌套表单字段(cocoon)的
出席人数
。情况如下:

模型如下:

培训模式

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
课堂培训
出席模式

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
课堂出勤
人物模型

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
class-Person
如果数据库中存在
人员
,则用户从下拉选择字段中选择该人员的姓名

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


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

关键是为嵌套属性设置一个
id
字段。Rails的行为是在
id
存在时更新现有记录,或者在
id
为空时创建新记录

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

我强烈推荐
cocoon
gem,它将为您的培训表单提供一个
link\u to\u add\u association
helper,您可以自动打开一个新的空表单。当实现时,您将使用如下方式调用帮助器

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


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

我使用了上面评论中的链接:

我用了维基上的最后一个例子

以下是我的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
将其添加到培训/\u考勤\u字段

.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', f, :person, data: {disable_with: "creating person"}
最后在培训/人员领域

.nested-fields
  .input-field
    = f.text_field :name
    = f.label :name
  .input-field
    = f.number_field :age
    = f.label :age
我添加了咖啡脚本:(在: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', 'before').data 'association-insertion-node', 'this'
    
    $('.attendance-person-fields').on 'cocoon:after-insert', ->
      
      $(this).children('.person_from_list').remove()
      $(this).children('a.add_fields').hide()

      return
    return

这是我在这里描述的示例之一:在示例项目中,这些链接也演示了如何准确地执行此操作。对于本例,这是wiki末尾的has_many through示例的最后一个示例。是的,但这里的示例是我的cocoon链接是这样的:link_to_add_association‘add Attentications’,f,:Attentications。因此,我是在培训表单中创建一个考勤(本例中为join表)并同时创建一个人。我认为这需要使用first_或_create方法Don do
f.考勤
do
f.人员
您可以忽略考勤,只需添加人员即可。