2016-03-09 161 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