我有三个类用户,驱动程序,公司。 每个公司或司机都属于一个用户。模型看起来像
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
为什么我不能创建Driver-instance。例如,如果我尝试d = Driver.new
,我会获得一个用户实例。d = Driver.new
=> #<Driver id: nil, email: nil, created_at: nil, updated_at: nil>
答案 0 :(得分:1)
这是Rails从模型类中猜测表名的方式。引用table_name
的{{3}}:
根据继承层次结构直接从
ActiveRecord::Base
降序的类的名称,猜测表名(强制小写)。因此,如果层次结构如下:Reply < Message < ActiveRecord::Base
,那么即使在Message
上调用,Reply
也会用于猜测表名。
你应该能够通过table_name=
setter强制使用正确的表名,例如:
class Driver < User
self.table_name = "drivers"
end
另一方面,我也不确定你的方法(具有这种继承)不会在其他地方引起问题。
答案 1 :(得分: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
,其列type
存储User
的记录,Company
和Driver
具有实际的班级名称(例如:Company
或Driver
等)。
如果您希望拥有单独的表users
,companies
和drivers
,因为每个表都有不同的列集,这是您将继承放入的唯一原因如果要共享一些常用功能,那么您应该将常用功能提取到modules
并将它们混合到这些模型中(仅通过继承ActiveRecord::Base
。
rails
,通过active_support
提供了名为concerns
的内容,将常用功能提取到模块中并直观地混合。
你可能可以逃避继承,并且仍然让这些模型指向具有self.table_name = "table_name"
声明的单独表。但这并不是一个好主意,因为它绕过rails
惯例并可能导致问题。
有关详细信息,请参阅ActiveRecord::Inheritance和ActiveSupport::Concern。