具有不同列Rails的相同模型

时间:2017-07-26 23:59:56

标签: ruby-on-rails ruby activerecord devise

我有2个用户角色DeveloperDriver。它们都属于User模型,但两者都有不同的详细信息,例如开发人员hourly_rateskillsexperiencefull_name和驱动程序cars_he_can_drive 1}},hours_drivenfull_name等。

他们有一些共同的列和一些不同的列。每个用户是否应该有单独的详细信息表(develop_detailsdriver_details)?而且,可以与他们建立关系。

否则我可以在所有列中使用相同的模型,只获取所需的列(其他列为零)。

更新 我在用户表中使用角色as和整数,然后使用枚举。 我正在使用Rails 5和4.3.0设计。

3 个答案:

答案 0 :(得分:4)

您可能希望查看单表继承

尝试继承Developer并共享一个Driver数据库表的Userusers。每个都是它自己的模型,允许你定义完全独立的关联,回调,验证,实例方法等......

它们共享所有相同的数据库列,User类中定义的任何内容都将被继承(并且可以被覆盖)。

您需要向type添加users列。还应为Developer表定义所有Driverusers列字段。

class AddTypeColumnToUsers < ActiveRecord::Migration
  def change
    add_column :users, :type, :string
  end
end

你的模特

class User < ApplicationRecord
end

class Driver < User
end

class Developer < User
end

Driver.new.type # => "Driver"
Developer.new.type # => "Developer"
User.new.type # => nil
User.new(type: 'Driver').class # => Driver
User.new(type: 'Developer').class # => Developer
User.new.class # => User

您可以像对待任何其他模型一样为它们运行单独的查询

Developer.all # queries all users WHERE type="Developer"
Driver.all # queries all users WHERE type="Driver"
User.all # queries all users no matter what type

像对待任何其他模型一样编写关联,ActiveRecord会处理其他所有事情。

class Company < ApplicationRecord
  has_many :users
  has_many :developers
  has_many :drivers
end

class User < ApplicationRecord
  belongs_to :company
end

class Driver < User
  belongs_to :company
end

class Developer < User
  belongs_to :company
end

c = Company.first
c.developers # => All developers that belong to the Company
c.drivers # => All drivers that belong to the Company
c.users # => All users (including developers and drivers) that belong to the Company

您还可以将enum用于type列,并根据需要覆盖默认的type列名称

class AddTypeColumnToUsers < ActiveRecord::Migration
  def change
    add_column :users, :role, :integer
  end
end

class User < ApplicationRecord
  self.inheritance_column = :role # This overrides the the "type" column name default

  enum role: { Driver: 0, Developer: 1 }
end

class Driver < User
end

class Developer < User
end

使用enum的问题是您必须使用大写名称,并且所有enum辅助方法和范围也将大写。

User.Driver # => Scope that returns all drivers
Driver.all # => same as User.Driver
User.first.Driver? # => Is the user a Driver?

http://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html

http://siawyoung.com/coding/ruby/rails/single-table-inheritance-in-rails-4.html

答案 1 :(得分:0)

这两种方法都可以解决您的问题。就个人而言,我只会有一个表格,因为Developer也是User的类型,而Driver也是User的类型。你可以这样做:

class User < ActiveRecord::Base
end

class Developer < User
end

class Driver < User 
end

如果用户是Developer,那么您可以为开发人员获取额外的列。没有列的零值可以很好。

答案 2 :(得分:0)

您可以根据不同列的数量来决定。如果不同列的数量多于此处的情况,请创建一个包含所有公共列的用户表和另外两个表(开发人员和驱动程序),这些表将包含一个user_id以与用户进行映射。

还创建一个名为roles的表。角色将包含id和role_name(驱动程序,开发人员等),并在users表中添加role_id列。即使你有两个以上的角色,这种结构也会给你灵活性。

class User < ActiveRecord::Base end

class Driver < ActiveRecord::Base belongs_to :user end

class Developer < ActiveRecord::Base belongs_to :user end

class Role < ActiveRecord::Base end