2013-05-09 105 views
0

我試圖用一個:has_many :through類型關聯,但我發現了以下錯誤:關於這類事情剛過了拼寫錯誤我是否需要爲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寶石,它不顯示任何我期望的關係ID。那麼,我需要創建一個WorkUnits表還是缺少一些東西?導軌指南沒有提到手動製作桌子。

編輯

這是我用來創建工作單元模型遷移和東西:

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

編輯從我schema.rb 2

摘錄:

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。那麼,爲什麼我的遷移不會爲我添加關聯信息?

+0

重新運行註釋:'bundle exec annotate'。您可能需要重新啓動開發服務器才能選取數據庫更改。 – 2013-05-09 20:09:02

+1

對於'has_many:through'關係,只有'WorkUnit'類的表必須與'project_id'和'developer_id'整數列一起存在。你可以檢查你的'db/schema.rb'是否是當前定義的。 – 2013-05-09 20:11:27

回答

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 

希望有所幫助。

0

WorkUnit的表格需要存在,無論這意味着它是通過腳手架自動生成還是由您手動編寫遷移。

如果您還沒有創建該表的遷移,則需要創建該遷移,因爲該表確實需要存在。

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 
+0

感謝您的回答。每個人都如此迅速地回答,我不知道誰是第一個。對不起,我沒有給你這個時間點 – 2013-05-09 20:20:08

+0

,爲什麼要在@ Thomas的答案中使用't.references'而不是't.belongs_to'或't.integer'?有什麼區別嗎? – 2013-05-10 06:34:12

+0

來自指南:*使用t.integer:supplier_id使外鍵命名顯而易見。在當前版本的Rails中,您可以使用t.references抽象出實現細節:供應商。*和*另一個助手稱爲引用(也可以用作belongs_to)。最簡單的形式只是增加了一些可讀性。* – Raindal 2013-05-10 13:23:53