我正在创建一个运动跟踪网站,其中包含一个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