我是否需要为:has_many:通过关联创建关联表?

时间:2013-05-09 20:06:11

标签: ruby-on-rails associations

我正在尝试使用:has_many :through类型关联,但我收到以下错误:

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: work_units.developer_id:

关于此类事情的许多其他帖子都有拼写错误,但我已经检查了我的。

class Developer < ActiveRecord::Base
  attr_accessible :skype_name, :language_ids, :user_attributes

  has_many :work_units
  has_many :projects, :through => :work_units
  ...
end

class Project < ActiveRecord::Base
  attr_accessible :complete, :description, :finalised, :price

  has_many :work_units
  has_many :developers, :through => :work_units
  ...
end

class WorkUnit < ActiveRecord::Base
  attr_accessible :hours_worked

  belongs_to :project
  belongs_to :developer
end

我已经db:migrate了,并没有抱怨。我确实犯了一个错误,不得不回滚数据库然后重新迁移,但我认为我做得对。我使用annotate gem并没有显示我期望的任何关系ID。那么,我是否需要创建一个WorkUnits表或者我错过了什么?导轨指南没有提到手工制作桌子。

修改

以下是我用于创建WorkUnit模型和迁移的迁移:

class CreateWorkUnits < ActiveRecord::Migration
  def change
    create_table :work_units do |t|
      t.integer :hours_worked, :default => 0
      t.timestamps
    end
  end
end

修改2

来自schema.rb的片段:

create_table "work_units", :force => true do |t|
  t.integer  "hours_worked", :default => 0
  t.datetime "created_at",                  :null => false
  t.datetime "updated_at",                  :null => false
end

create_table "projects", :force => true do |t|
  t.string   "description"
  t.decimal  "price",       :precision => 8, :scale => 2
  t.boolean  "complete",    :default => false
  t.datetime "created_at",  :null => false
  t.datetime "updated_at",  :null => false
end

同样适用于:developers。那么,为什么我的迁移不能为我添加关联信息呢?

4 个答案:

答案 0 :(得分:3)

您的WorkUnit迁移应如下所示:

class CreateWorkUnits < ActiveRecord::Migration
  def change
    create_table :work_units do |t|
      t.integer :hours_worked, :default => 0
      t.references :developer
      t.references :project
      t.timestamps
    end
    add_index :work_units, :developer_id
    add_index :work_units, :project_id
  end
end

答案 1 :(得分:1)

您需要将外键添加到work_units表。

class CreateWorkUnits < ActiveRecord::Migration
  def change
    create_table :work_units do |t|
      t.integer :hours_worked, :default => 0
      t.integer :project_id, null: false
      t.integer :developer_id, null: false
      t.timestamps
    end

    add_index :work_units, :project_id
    add_index :work_units, :developer_id
  end
end

另一种方式:

class CreateWorkUnits < ActiveRecord::Migration
  def change
    create_table :work_units do |t|
      t.integer :hours_worked, :default => 0
      t.belongs_to :project
      t.belongs_to :developer
      t.timestamps
    end

    add_index :work_units, :project_id
    add_index :work_units, :developer_id
  end
end

您还可以在生成模型时定义这些字段,然后它们将自动添加到迁移中,如第二个代码段所示。

$ rails g model WorkUnit hours_worked:integer project:belongs_to developer:belongs_to

希望有所帮助。

答案 2 :(得分:0)

WorkUnit的表格需要存在,这是否意味着迁移是通过脚手架自动生成的,或者迁移是由您手动编写的。

如果您还没有创建该表的迁移,则需要创建该迁移,因为该表确实需要存在。

答案 3 :(得分:0)

您确实需要一个包含project_id和developer_id列的work_units表。

如果您不知道如何创建表格,请查看http://xyzpub.com/en/ruby-on-rails/3.2/activerecord_datenbank_anlegen.html