如何获取此嵌套表单以创建新对象

时间:2016-09-25 10:43:34

标签: ruby-on-rails nested-forms

My Rails 5应用程序包括两个模型,Activity和Timeslot。

activity.rb

class Activity < ApplicationRecord
  belongs_to :club
  has_many :timeslots, :dependent => :destroy
  accepts_nested_attributes_for :timeslots
  validates :club_id, presence: true
  validates :name, presence: true, length: { maximum: 50 }
end

timeslot.rb

class Timeslot < ApplicationRecord
    belongs_to :activity
    validates :time_start, presence: true
    validates :time_end, presence: true
    validates :day, presence: true
    #validates :activity_id, presence: true (I realised this was causing one of the errors I had)
    default_scope -> { order(day: :asc) }
end

当我创建我的活动时,我还想在同一页面上创建它的第一个时间段,相同的形式。

new.html.erb

<%= form_for(@activity) do |f| %>
    <%= render 'shared/error_messages', object: f.object %>
    <div class="field">
        <%= f.label :name, "Class name" %>*
        <%= f.text_field :name, class: 'form-control' %>

            <%= f.fields_for :timeslots do |timeslots_form| %>
                    <%= timeslots_form.label :time_start, "Start time" %>
                    <%= timeslots_form.time_select :time_start %>

                    <%= timeslots_form.label :time_end, "End time" %>
                    <%= timeslots_form.time_select :time_end %>

                    <%= timeslots_form.label :day %>
                    <%= timeslots_form.select :day, (0..6).map {|d| [Date::DAYNAMES[d], d]} %>
            <% end %>
    </div>
    <%= f.submit "Create class", class: "btn btn-primary" %>
<% end %>

我的编辑/更新版本似乎工作正常。

activities_controller.rb

class ActivitiesController < ApplicationController
 ...

def new
    @activity = Activity.new
    @activity.timeslots.build
end

def create
    @activity = current_club.activities.build(activity_params)
    #@activity.timeslots.first.activity_id = @activity.id (I thought this might solve the problem, but didn't)
    if @activity.save
        flash[:success] = "New class created!"
        redirect_to activities_path
    else
        render 'new'
    end
end

def edit
    @activity = current_club.activities.find_by(id: params[:id])
    @activity.timeslots.build
end

def update
    @activity = current_club.activities.find_by(id: params[:id])
    if @activity.update_attributes(activity_params)
        flash[:sucess] = "Class updated!"
        redirect_to edit_activity_path(@activity)
    else
        render 'edit'
    end
end
...

private

    def activity_params
        params.require(:activity).permit(:name, :active, #active is set to default: true
                                         :timeslots_attributes => [:id,
                                                                   :time_start,
                                                                   :time_end,
                                                                   :day,
                                                                   :active])
    end
end

但每当我尝试创建一个新活动时,我都会收到错误消息“Timeslots活动必须存在”。

我觉得它在创建活动之前尝试为时间段分配activity_id,但我不确定。我已经尝试了很多东西(其中一些我已经在评论表单中包含在我的例子中)但是我无法弄清楚为什么我会收到这个错误。

更新:添加错误日志

Started POST "/activities" for 127.0.0.1 at 2016-09-25 18:04:51 +0700
Processing by ActivitiesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"xp+dBcWC4cjI6FLpIqhU0RzM4ldZ4JpkFLSyAXcmifL73QqWz6R65EHm/Tj7QxlXnWiBA0axjVXvMZHQ+XKA9A==", "activity"=>{"name"=>"Newest class", "timeslots_attributes"=>{"0"=>{"time_start(1i)"=>"2016", "time_start(2i)"=>"9", "time_start(3i)"=>"25", "time_start(4i)"=>"12", "time_start(5i)"=>"00", "time_end(1i)"=>"2016", "time_end(2i)"=>"9", "time_end(3i)"=>"25", "time_end(4i)"=>"13", "time_end(5i)"=>"30", "day"=>"4"}}}, "commit"=>"Create class"}
  Club Load (0.2ms)  SELECT  "clubs".* FROM "clubs" WHERE "clubs"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
   (0.1ms)  begin transaction
   (0.1ms)  rollback transaction
  Rendering activities/new.html.erb within layouts/application
  Rendered shared/_error_messages.html.erb (1.5ms)
  Rendered activities/new.html.erb within layouts/application (16.9ms)
  Rendered layouts/_rails_default.html.erb (58.5ms)
  Rendered layouts/_shim.html.erb (0.5ms)
  Rendered layouts/_header.html.erb (1.7ms)
  Rendered layouts/_footer.html.erb (0.8ms)
Completed 200 OK in 111ms (Views: 93.9ms | ActiveRecord: 0.3ms)

1 个答案:

答案 0 :(得分:0)

您收到此错误,因为Rails 5默认情况下需要belongs_to属性。此外,保存机制如下:

validate your parent model
validate your child model # validation fails here because parent doesn't have an id yet, because it hasn't been saved
save parent model
save child model

解决此问题的方法是:

class Activity < AR
  has_many :timeslots, dependent: :destroy, inverse_of: :activity
  accepts_nested_attributes_for :timeslots
end

class Timeslot < AR
  belongs_to :activity, inverse_of: :timeslot
end

您可以详细了解herehere