2016-03-09 156 views
0

我有這三類用戶,驅動程序,公司。每個公司或司機屬於一個用戶。該模型看起來像Rails繼承子類

class Company < User 
    has_many :driver 
end 

class Driver < User 
end 

class User < ActiveRecord::Base 
    enum role: [:admin, :support, :B2B , :B2C] 
end 

和數據庫看起來像

class CreateUsers < ActiveRecord::Migration 
def change 
create_table :users do |t| 
    t.string :email 

    t.timestamps null: false 
    end 
end 
end 

class CreateCompanies < ActiveRecord::Migration 
def change 
    create_table :companies do |t| 
    t.string :comp_name 
    t.string :first_name_counterpart 
    t.string :last_name_counterpart 
    t.string :iban_nr 
    t.string :bic 
    t.string :email_counterpart 
    t.string :addresse 
    t.string :city 
    t.string :zip 

    t.references :user 
    t.timestamps null: false 
    end 
end 
end 

class CreateDrivers < ActiveRecord::Migration 
def change 
    create_table :drivers do |t| 
    t.string :first_name 
    t.string :last_name 
    t.date :birthday 
    t.integer :sex 
    t.integer :dpi 
    t.integer :score 


    t.references :user 
    t.timestamps null: false 
    end 
end 
end 

爲什麼我不能創建一個驅動程序實例。例如,如果我嘗試d = Driver.new,我得到一個用戶實例。 d = Driver.new => #<Driver id: nil, email: nil, created_at: nil, updated_at: nil>

回答

1

這就是Rails如何從模型類中猜測表名。從ActiveRecord docs報價爲table_name

猜測基礎上的繼承層次直接從ActiveRecord::Base降類的名稱表名(在強制小寫)。因此,如果層次結構如下所示:Reply < Message < ActiveRecord::Base,那麼即使在Reply上調用時,也會使用Message來猜測表名。

您應該能夠通過table_name=二傳手強制正確的表名,如:

class Driver < User 
    self.table_name = "drivers" 
end 

在另一方面,我也不能肯定你的做法(有這樣的繼承)不會在其他地方造成問題。

+0

我很困惑。我想在用戶中同時存儲每個公司和驅動程序。我的意思是,當我創建一個驅動程序應自動創建一個用戶的電子郵件和密碼。如果我錯了,請糾正我! 但是當我在控制檯中創建一個驅動程序時,得到nil作爲'User.all'的答案只是沒有 – Arthur

+0

啊哈,我不認爲Rails是這樣工作的。你在上面的註釋中寫了什麼,類似於集合(例如has_many,belongs_to),但實際情況並非如此,因爲如果我正確地得到它,Driver與User相同,只有一些功能超出User。所以它不像「駕駛員也有/屬於用戶」。在那種情況下,我認爲STI方法實際上就是你所追求的,請參閱@Dharam的答案。 – BoraMa

1

如果你有遺傳模型像你這樣的:

class User < ActiveRecord::Base 
    enum role: [:admin, :support, :B2B , :B2C] 
end 

class Company < User 
    has_many :driver 
end 

class Driver < User 
end 

rails推斷你是單表繼承(STI)後,預計有剛有基表users與存儲記錄的列typeUser,CompanyDriver與實際類名(例如:CompanyDriver等)。

如果你寧願希望有單獨的表userscompaniesdrivers因爲每表有不同的一組列,爲什麼你把繼承到位的唯一原因是有一些共同的功能,那麼你應該提取通用的功能爲modules,並將它們混合到那些模型(由ActiveRecord::Base只是繼承。

rails,通過active_support提供什麼叫concerns提取常見功能集成到模塊,並將其直觀地混合。

您可能會遺漏繼承,並仍然有這些模型指向與self.table_name = "table_name"聲明分開的表。但這不是一個好主意,因爲它遵循約定並可能導致問題。

有關更多信息,請參閱ActiveRecord::InheritanceActiveSupport::Concern

+0

你的意思是,如果我創建一個新的驅動程序實例,這將存儲在用戶? – Arthur