无法使accepts_nested_attributes_for工作

时间:2016-01-27 03:00:49

标签: ruby-on-rails

我有两个模型,A WorkoutWorkoutEquipment

class Workout < ActiveRecord::Base

  belongs_to :exercise
  belongs_to :session
  belongs_to :workout_equipments

  accepts_nested_attributes_for :workout_equipments
end

class WorkoutEquipment < ActiveRecord::Base

  has_many :workout
  has_many :equipment

end

My / new看起来像这样:

enter image description here

背后的形式看起来像这样:

<%= form_for(@workout) do |f| %>
  <% if @workout.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@workout.errors.count, "error") %> prohibited this workout from being saved:</h2>

      <ul>
      <% @workout.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>


  <div class="field">
    <%= f.label :exercise_id %><br>
    <%= f.select :exercise_id, Exercise.all.collect{|t| [t.name, t.id]}, {prompt: true} %>
  </div>
  <div class="field">
    <%= f.label :session_id %><br>
    <%= f.select :session_id, Session.all.collect{|t| [t.when, t.id]}, {prompt: true} %>
  </div>

    <%= fields_for(:workout_equipment) do |u| %>
        <div class="field">
        <%= u.label :equipment_id %><br>
        <%= u.select :equipment_id, Equipment.all.collect{|t| [t.name, t.id]}, {prompt: true} %>
        </div>
        <div class="field">
        <%= u.label :equipment_weight %><br>
        <%= u.number_field :weight %>
        </div>
    <% end %>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

但是,当我提交时,尽管accepts_nested_attributes_for :workout_equipmentsworkout_equipments.id并未放入workout对象。输出日志如下所示:

ActiveRecord::SchemaMigration Load (0.1ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by WorkoutsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"OSh3xA+usL4/0MAtvRqKio2Vcz/ziLdQ1Rj2vh5zLCXxlVhofoCGh88ssEn+IOc2AXhn3sXWsZn3bIO93hyJMA==", "workout"=>{"exercise_id"=>"4", "session_id"=>"3"}, "workout_equipment"=>{"equipment_id"=>"4", "weight"=>"9001"}, "commit"=>"Create Workout"}
   (0.1ms)  begin transaction
  SQL (0.3ms)  INSERT INTO "workout_equipments" ("equipment_id", "weight", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["equipment_id", 4], ["weight", 9001.0], ["created_at", "2016-01-27 02:56:56.611731"], ["updated_at", "2016-01-27 02:56:56.611731"]]
   (6.1ms)  commit transaction
   (0.1ms)  begin transaction
  SQL (0.3ms)  INSERT INTO "workouts" ("exercise_id", "session_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["exercise_id", 4], ["session_id", 3], ["created_at", "2016-01-27 02:56:56.640104"], ["updated_at", "2016-01-27 02:56:56.640104"]]
   (7.4ms)  commit transaction
   (0.0ms)  begin transaction
   (0.0ms)  commit transaction

如您所见,仅记录exercise_idsession_id。 我的相关控制器操作如下:

def create
    @workout_equipment = WorkoutEquipment.create(workout_equipment_params)
    @workout = Workout.create(workout_params)

    respond_to do |format|
      if @workout.save
        format.html { redirect_to @workout, notice: 'Workout was successfully created.' }
        format.json { render :show, status: :created, location: @workout }
      else
        format.html { render :new }
        format.json { render json: @workout.errors, status: :unprocessable_entity }
      end
    end
  end

def workout_equipment_params
      params.require(:workout_equipment).permit(:workout_id, :equipment_id, :weight)
end

def workout_params
      params.require(:workout).permit(:exercise_id, :session_id, :workout_equipments_id)
end

我还需要为params方法做些什么吗?

2 个答案:

答案 0 :(得分:2)

在你的模型中,belongs_to&amp; accepts_nested_attributes_for方法应该采用:workout_equipment(注意它是单数形式,而不是复数形式)

    class Workout < ActiveRecord::Base

      belongs_to :exercise
      belongs_to :session
      belongs_to :workout_equipment

      accepts_nested_attributes_for :workout_equipment
    end

在您的控制器中,您不需要构建workout_equipment对象,因为nested_attributes会为您执行此操作:

    def create
        @workout = Workout.create(workout_params)

        respond_to do |format|
          if @workout.save
            format.html { redirect_to @workout, notice: 'Workout was successfully created.' }
            format.json { render :show, status: :created, location: @workout }
          else
            format.html { render :new }
            format.json { render json: @workout.errors, status: :unprocessable_entity }
          end
        end
    end

出于同样的原因,您不需要workout_equipment_params并且应该丰富您的workout_params方法:

    def workout_params
          params.require(:workout).permit(:exercise_id, :session_id, workout_equipment_attributes: [:id, :workout_id, :equipment_id, :weight])
    end

我可能误解了您在每个模型中的属性,因此相应地修改了参数。通常,您将nested_attributes发送到workout_equipment_attributes哈希。

祝你好运!

答案 1 :(得分:1)

您需要更改关联名称(当plural}时,您正在使用singular):

#app/models/workout.rb
class Workout < ActiveRecord::Base
   belongs_to :workout
   belongs_to :session
   belongs_to :workout_equipment
   accepts_nested_attributes_for :workout_equipment
end

#app/models/workout_equipment.rb
class WorkoutEquipment < ActiveRecord::Base
  has_many :workouts
end

#app/controllers/workouts_controller.rb
class WorkoutsController < ApplicationController
   def new
     @equipment = Equipment.all
     @workout = Workout.new
     @workout.build_workout_exercise
   end

   def create
     @workout = Workout.new workout_params
     @workout.save
   end

   private

   def workout_params
     params.require(:workout).permit(workout_exercise_attributes: [:equipment_id, :weight])
   end
end

#app/views/workouts/new.html.erb
<%= form_for @workout do |f| %>
  <%= f.fields_for :workout_exericse do |w| %>
     <%= w.collection_select :equipment_id, @equipment, :id, :name %>
     <%= w.number_field :weight %>
  <% end %>
  <%= f.submit %>
<% end %>