Rails Create has_many_through不会创建记录

时间:2014-07-14 02:43:07

标签: postgresql ruby-on-rails-4 formtastic

我正在创建一个运动跟踪网站,其中包含一个Workout表,一个WorkoutExercise表和一个Exercise表(这只是一些模式)。

我一直在尝试创建一个" WorkoutExercise"从编辑/创建锻炼表单。我使用Formtastic,我的表单会显示用户的练习列表,但是当我提交表单时,不会创建WorkoutExercises,但会创建或更新锻炼。

我已经搜索了谷歌和stackoverflow这个问题一天半没有多少帮助。从我所知道的,这应该"只是工作",我想我错过了一些简单的事情。这是我的第一个RoR网站,所以请耐心等待:):

另外需要注意的是,如果我在PSQL中手动创建关系,我会创建一个显示关系的练习,但是当我点击提交时,会从数据库中删除WorkoutExercise记录。

这3个表的数据库模式:

  create_table "exercises", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "user_id"
    t.text     "notes"
    t.decimal  "base_weight"
  end

  create_table "workout_exercises", force: true do |t|
    t.integer  "workout_id"
    t.integer  "exercise_id"
    t.integer  "exercise_order"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "workouts", force: true do |t|
    t.integer  "user_id"
    t.text     "description"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "name"
  end

练习模型:

class Exercise < ActiveRecord::Base
   has_many :weight_logs, dependent: :destroy
   belongs_to :user
   has_many :workout_exercises
   has_many :workouts, :through => :workout_exercises
   ...

WorkoutExercise模型(多对多表)

class WorkoutExercise < ActiveRecord::Base
    belongs_to :exercise
    belongs_to :workout
    accepts_nested_attributes_for :workout
    #default_scope -> { order('exercise_order ASC') }
    validates :exercise_id, presence: true
    validates :workout_id, presence: true
    validates :exercise_order, presence: true
end

锻炼模型:

class Workout < ActiveRecord::Base
    has_many :workout_exercises
    has_many :exercises, :through => :workout_exercises, :class_name => 'Exercise'
    belongs_to :user
    accepts_nested_attributes_for :exercises
    accepts_nested_attributes_for :workout_exercises
    ...

Workouts_conroller.rb

class WorkoutsController < ApplicationController
  before_action :set_workout, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!
  before_action :correct_user, only: :destroy
  # GET /workouts
  # GET /workouts.json
  def index
    @workouts = Workout.all
  end

  # GET /workouts/1
  # GET /workouts/1.json
  def show
  end

  def add_exercise
  end
  # GET /workouts/new
  def new
    @workout = current_user.workouts.new
    @exercises = current_user.exercises.all

  end

  # GET /workouts/1/edit
  def edit
    @exercises = @workout.exercises.build
  end

  # POST /workouts
  # POST /workouts.json
  def create
    @workout = current_user.workouts.build(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

  # PATCH/PUT /workouts/1
  # PATCH/PUT /workouts/1.json
  def update
   respond_to do |format|
     if @workout.update(workout_params)
       format.html { redirect_to @workout, notice: 'Workout was successfully updated.' }
       format.json { render :show, status: :ok, location: @workout }
     else
       format.html { render :edit }
       format.json { render json: @workout.errors, status: :unprocessable_entity }
     end
   end
  end

  # DELETE /workouts/1
  # DELETE /workouts/1.json
  def destroy
    @workout.destroy
    respond_to do |format|
      format.html { redirect_to workouts_url, notice: 'Workout was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_workout
      @workout = Workout.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def workout_params
      params.require(:workout).permit(:description, :name,
                        :exercise_ids => [:exercise_id])
    end

    def correct_user
        @workout = current_user.workouts.find_by(id: params[:id])
      redirect_to root_url if @workout.nil?
    end
end

Rails服务器登录保存:

Started PATCH "/workouts/6" for 127.0.0.1 at 2014-07-13 19:30:05 -0700
Processing by WorkoutsController#update as HTML
  Parameters: {"utf8"=>"v", "authenticity_token"=>"WY2P1Z7/g/PoG5iB6VufDNOG7Hyk7tnJQzTT00CpNTM=", "workout"=>{"name"=>"sad", "description"=>"asd", "exercise_ids"=>["", "17", "23",
"9", "15", "14", "18"]}, "commit"=>"Update Workout", "id"=>"6"}
  ?[1m?[36mWorkout Load (0.0ms)?[0m  ?[1mSELECT  "workouts".* FROM "workouts"  WHERE "workouts"."id" = $1 LIMIT 1?[0m  [["id", 6]]
  ?[1m?[35mUser Load (1.0ms)?[0m  SELECT  "users".* FROM "users"  WHERE "users"."id" = 1  ORDER BY "users"."id" ASC LIMIT 1
  ?[1m?[36m (0.0ms)?[0m  ?[1mBEGIN?[0m
  ?[1m?[35mExercise Load (0.0ms)?[0m  SELECT "exercises".* FROM "exercises" INNER JOIN "workout_exercises" ON "exercises"."id" = "workout_exercises"."exercise_id" WHERE "workout_ex
ercises"."workout_id" = $1  ORDER BY name ASC  [["workout_id", 6]]
  ?[1m?[36m (0.0ms)?[0m  ?[1mCOMMIT?[0m
Redirected to http://localhost:3000/workouts/6

这也是我的形式:

<%= semantic_form_for @workout do |f| %>
  <%= f.inputs do %>
    <%= f.input :name %>
    <%= f.text_area :description %>
    <%= f.input :exercises, :as => :check_boxes, :collection => Exercise.where(:user_id => @workout.user_id) %>
  <% end%>

  <%= f.actions %>
<% end %>

修改 我无法回答我的问题,但我找到了解决方法。我不认为这是最好的解决方案,但它确实有效!这是在我的workouts_controller.rb

的def更新中添加的
 if @workout.update(workout_params)
        params[:workout].each do |key,value|
            if key == 'exercise_ids'
                @exercises = Exercise.find(value.reject!{|a| a==""})
                @workout.exercises << @exercises        
            end
        end

0 个答案:

没有答案