Same Model with different columns Rails

微笑、不失礼 提交于 2019-12-11 03:43:04

问题


I have 2 user roles Developer and Driver. They both are under an User model, but also both have different details such as Developer has hourly_rate, skills, experience, full_name and Driver has cars_he_can_drive, hours_driven, full_name etc.

They have some common columns and some different ones as well. Should there be a separate detail table (develop_details, driver_details) for each of the User? and further, relationships can be made with them.

Else I can have same model with all columns and fetch only the ones required (others will be nil ofcourse).

UPDATE Im using role as and integer in user table and then using enums. I'm using Rails 5 with devise 4.3.0.


回答1:


You probably want to look at Single Table Inheritance

Try a Developer and Driver that both inherit from User and share one users database table. Each is effectively its own model, allowing you to define totally independent associations, callbacks, validations, instance methods, etc...

They share all of the same database columns, and anything defined in the User class will be inherited (and can be overwritten).

You will need to add a type column to users. All of the Developer and Driver columns fields should be defined for the users table as well.

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

And your models

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

You can run separate queries for them just as you would any other model

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

Write your associations just as you would with any other model, and ActiveRecord will take care of everything else.

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

You can also use enum for the type column, and override the default type column name if you wish

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

The catch with using enum is you will have to use the capitalized name, and all of your enum helper methods and scopes will be capitalized as well.

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




回答2:


Well both approach will solve your problem. Personally I will only have a single table because Developer is also type of User and Driver is also type of User. You can do something like this:

class User < ActiveRecord::Base
end

class Developer < User
end

class Driver < User 
end

If user is Developer then you can fetch extra columns for developers. It's fine to have few column with nil value.




回答3:


You can decide this based on the number of different columns. If the number of different columns is more which seems to be the case here, Create a user table which contains all the common columns and 2 more tables(developers and drivers) which will contain a user_id to map with the user.

Also create a table named roles. Roles will contain id and role_name(driver, developer etc.) and add role_id column in users table. This structure will give you the flexibility even if you have more than 2 roles.

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



来源:https://stackoverflow.com/questions/45339248/same-model-with-different-columns-rails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!