【问题标题】:rails model has_many :through associationsrails model has_many:通过关联
【发布时间】:2013-07-10 01:34:49
【问题描述】:

我正在努力解决我的关系,但我无法使用这些关联。

所以我有三个模型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 是未定义的。有没有人有任何想法?

【问题讨论】:

  • 您运行迁移了吗?请向我们展示您的 3 张桌子。而且我认为你应该暂时忽略彦浩的建议。您的代码似乎是正确的,因此您现在不必更改它。您还缺少其他东西。
  • @Ashitaka 我添加了上面的表格,是否与 CreateWorkoutExercises 表格为空有关?这是我第一次使用 habtm。
  • 好的,就是这样。您缺少在两个表之间建立连接的 id。您现在可能想要重新创建迁移。我认为rake db:reset 会完成这项工作(不过它会删除你的所有记录)。

标签: ruby-on-rails ruby


【解决方案1】:

好的,您的 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 关系,则必须将您的表强制命名为“ExercesWorkout”。注意锻炼是如何在锻炼之前进行的。名称必须按字母顺序排列。不要问我为什么,这只是一个 Rails 约定。

因此,在这种情况下,您可以将表命名为 WorkoutExercises。但是如果我是你,我会把它改成ExercesWorkout,以防万一,这样你就不会弄错了。

【讨论】:

  • 谢谢@Ashitaka。在Rails 4中,列和索引迁移可以写在一行t.references :exercise, index: true
【解决方案2】:

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-27
  • 2013-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-24
  • 2017-11-27
相关资源
最近更新 更多