Rails模型has_many :through关联

8
我正在尝试解决我的关系问题,但我在使用关联时遇到了麻烦。
所以我有三个模型WorkoutExerciseWorkoutExercise。训练应该有很多锻炼,而锻炼应该有不同的训练,因此我写了:
class Workout < ActiveRecord::Base
  has_many :workout_exercises
  has_many :exercises, :through => :workout_exercises
end

class Exercise < ActiveRecord::Base
  has_many :workout_exercises
  has_many :workouts, :through => :workout_exercises
end

class WorkoutExercise < ActiveRecord::Base
  belongs_to :exercise
  belongs_to :workout
end

我正在进行一些测试,但是当我创建一个训练、练习并将它们组合在训练练习类中时,测试不通过。无法像这样访问训练中的练习:

Workout.create
Exercise.create
WorkoutExercise.create(:workout => Workout.first, :exercise => Exercise.first)
work = Workout.first
work.exercises.count #This line causes the error: undefined method exercises

我的数据库表长这样:

class CreateWorkouts < ActiveRecord::Migration
  def change
    create_table :workouts do |t|
      t.string :title
      t.text :description
      t.float :score
      t.timestamps
    end
  end
end 

class CreateExercises < ActiveRecord::Migration
  def change
    create_table :exercises do |t|
      t.string :title
      t.text :description
      t.float :value
      t.timestamps
    end
  end
end

class CreateWorkoutExercises < ActiveRecord::Migration
  def change
    create_table :workout_exercises do |t|
      t.timestamps
    end
  end
end

当我运行这个测试时,它显示exercises未定义。有人有任何想法吗?

你运行了迁移吗?请向我们展示你的三个表。我认为你应该暂时忽略Yanhao的建议。你的代码似乎是正确的,所以现在不需要更改它。你还缺少别的什么东西。 - Ashitaka
@Ashitaka,我已经添加了上面的表格,这是否与CreateWorkoutExercises表为空有关?这是我第一次使用habtm。 - trev9065
好的,就是这样。你缺少了建立两个表之间连接的id。现在你可能想要重新创建迁移。我认为 rake db:reset 可以完成这项工作(但它会删除所有记录)。 - Ashitaka
2个回答

11

好的,你的WorkoutExercises表格不能为空。它应该如下所示:

class CreateWorkoutExercises < ActiveRecord::Migration
  def change
    create_table :WorkoutExercises do |t|
      t.integer :exercise_id, :null => false
      t.integer :workout_id, :null => false

      t.timestamps
    end

    # I only added theses indexes so theoretically your database queries are faster.
    # If you don't plan on having many records, you can leave these 2 lines out.
    add_index :WorkoutExercises, :exercise_id
    add_index :WorkoutExercises, :workout_id
  end
end

此外,您可以随意命名这个表,它不一定非要叫做WorkoutExercises。 然而,如果您使用的是has_and_belongs_to_many关系,则您的表必须强制命名为ExercisesWorkout。注意,Exercises出现在Workout之前。名称必须按字母顺序排列。不要问我为什么,这只是Rails的惯例。
因此,在这种情况下,将表命名为WorkoutExercises就可以了。但如果我是您,我会将其改为ExercisesWorkout,以防万一,这样您就永远不会弄错了。

1
感谢@Ashitaka。在Rails 4中,列和索引迁移可以写在一行中t.references :exercise, index: true - scarver2

1

我相信has_and_belongs_to_many关联已经被弃用。https://dev59.com/kVzUa4cB1Zd3GeqP3XR- - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接