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

大城市里の小女人 提交于 2019-12-22 01:42:26

问题


In my Rails application, I am attempting to set up creation form for a TrainingClass model. 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. Unfortunately, whenever I submit the form I get the error message: 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. (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:

ClassMeeting Model:

# == 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:

# == 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:

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):

<%= 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 %>

回答1:


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. 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:

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



回答2:


I pored over this example, trying out the differences with my code, but in the end my problem was fixed by using :inverse_of.

See accepts_nested_attributes_for child association validation failing



来源:https://stackoverflow.com/questions/11778938/in-rails-how-do-i-create-nested-objects-using-accepts-nested-attributes-for

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!