问题
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