简体   繁体   English

在Rails中,如何使用accepts_nested_attributes_for创建嵌套对象?

[英]In Rails, how do I create nested objects using accepts_nested_attributes_for?

In my Rails application, I am attempting to set up creation form for a TrainingClass model. 在我的Rails应用程序中,我试图为TrainingClass模型设置创建表单。 I want this form to allow the user to create multiple ClassMeeting models (which have a belongs_to relationship with the TrainingClass model) within the same form, and I am using accepts_nested_attributes_for to do this. 我希望此表单允许用户在同一表单内创建多个ClassMeeting模型(与TrainingClass模型具有属植物关系),并且我正在使用accepts_nested_attributes_for做到这一点。 Unfortunately, whenever I submit the form I get the error message: Meetings class can't be blank . 不幸的是,每当我提交表单时,我都会收到错误消息: Meetings class can't be blank

I realize that this is because ClassMeeting has validates :class_id, presence: true , and because TrainingClass can't have an id until after it is saved, but I'm not sure of the right way to get around this. 我意识到这是因为ClassMeeting具有validates :class_id, presence: true ,并且因为TrainingClass在保存之前无法拥有ID,但是我不确定解决此问题的正确方法。 (I can think of a few possible ways, but they aren't exactly elegant solutions.) Any ideas? (我可以想到几种可能的方法,但它们并不是精确的解决方案。)有什么想法吗? I'd appreciate any help you can give me. 谢谢您能给我的任何帮助。

Note: I realize quite a few questions similar to this have been asked in the past. 注意:我知道过去已经问过很多类似的问题。 However, most of those questions are old and have outdated answers, and none of them solved my problem. 但是,这些问题大多数都是过时的,并且答案已经过时,而且都没有解决我的问题。


Here is my code. 这是我的代码。 Keep in mind that although I have simplified some aspects of it for brevity, the relationship between the ClassMeeting and TrainingClass models was left untouched: 请记住,尽管为简洁起见,我简化了某些方面,但ClassMeetingTrainingClass模型之间的关系保持不变:

ClassMeeting Model: ClassMeeting模型:

# == Schema Information
#
# Table name: class_meetings
#
#  id         :integer         not null, primary key
#  class_id   :integer
#  start      :datetime
#  end        :datetime
#  location   :string(255)
#  created_at :datetime        not null
#  updated_at :datetime        not null
#

class ClassMeeting < ActiveRecord::Base
  attr_accessible :start, :end, :location

  validates :class_id, presence: true
  validates :start, presence: true
  validates :end, presence: true
  validates :location, presence: true, length: {maximum: 255}

  belongs_to :training_class, foreign_key: :class_id, inverse_of: :meetings
end

TrainingClass Model: TrainingClass模型:

# == Schema Information
#
# Table name: training_classes
#
#  id            :integer         not null, primary key
#  description   :string(255)
#  created_at    :datetime        not null
#  updated_at    :datetime        not null
#

class TrainingClass < ActiveRecord::Base
  attr_accessible :description, :meetings_attributes

  validates :description, length: {maximum: 255}

  has_many :meetings, class_name: :ClassMeeting, foreign_key: :class_id, inverse_of: :training_class

  accepts_nested_attributes_for :meetings, allow_destroy: true
end

TrainingClasses Controller: TrainingClasses控制器:

class TrainingClassesController < ApplicationController
  def new
    @training_class = TrainingClass.new()
    @training_class.meetings.build
  end

  def create
    @training_class = TrainingClass.new()

    if @training_class.update_attributes(params[:training_class])
        redirect_to @training_class, notice: 'Class was successfully created.'
    else
        render "new"
    end
  end
end

TrainingClass Form (View): TrainingClass表格(查看):

<%= form_for @training_class do |f| %>
    <%= render 'shared/error_messages', object: f.object %>

    <%= f.text_area :description %>

    <h2>Schedule</h2>
    <%= f.fields_for :meetings do |meeting| %>
        <%= meeting.label :start, "Start of Meeting:" %>
        <%= meeting.text_field :start %>

        <%= meeting.label :end, "End of Meeting:" %>
        <%= meeting.text_field :end %>

        <%= meeting.label :location, "Location:" %>
        <%= meeting.text_field :location %>
    <% end %>

    <%= f.submit class:"btn btn-large btn-primary" %>
<% end %>

All right, I found the solution to my problem. 好的,我找到了解决问题的方法。 All I need to do is validate the presence of training_class instead of class_id in the ClassMeeting model. 我需要做的就是验证ClassMeeting模型中training_class的存在,而不是class_id的存在。 That way the existence of a training class is still validated, but the validator doesn't interfere with accepts_nested_attributes_for 's method of saving the model: 这样,仍然可以验证训练类的存在,但是验证器不会干扰accepts_nested_attributes_for的模型保存方法:

class ClassMeeting < ActiveRecord::Base
  attr_accessible :start, :end, :location

  validates :training_class, presence: true # :training_class instead of :class_id
  validates :start, presence: true
  validates :end, presence: true
  validates :location, presence: true, length: {maximum: 255}

  belongs_to :training_class, foreign_key: :class_id, inverse_of: :meetings
end

I pored over this example, trying out the differences with my code, but in the end my problem was fixed by using :inverse_of . 我仔细研究了这个示例,尝试了与代码的差异,但最终,我的问题通过使用:inverse_of得以解决。

See accepts_nested_attributes_for child association validation failing 有关子关联验证失败的信息,请参见accepts_nested_attributes_

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM