rails model has_many:通过关联

时间:2012-03-10 01:25:42

标签: ruby-on-rails ruby

我正在尝试解决我的关系,但我在使用关联时遇到了麻烦。

所以我有三个模型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_exercise类,测试就不会通过。它不会让我像这样访问锻炼中的练习:

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未定义。有没有人有任何想法?

2 个答案:

答案 0 :(得分: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。注意练习在锻炼之前是如何产生的。名称必须按字母顺序排列。不要问我为什么,这只是一个Rails惯例。

因此,在这种情况下,您可以将您的表名为WorkoutExercises。但如果我是你,我会把它改为ExercisesWorkout,以防万一,所以你永远不会错。

答案 1 :(得分:1)

您的代码看起来不错。错误可能has_and_belongs_to_many是更好的选择。见Choosing Between has_many :through and has_and_belongs_to_many