2017-07-26 48 views
2

我有2個用戶角色DeveloperDriver。他們都是下User模式,但也都有不同的細節,如開發具有hourly_rateskillsexperiencefull_name和驅動程序具有cars_he_can_drivehours_drivenfull_name與不同列相同的模型導軌

他們有一些共同的列和一些不同的人,以及。是否應爲每個用戶提供單獨的明細表(develop_detailsdriver_details)?並進一步與他們建立關係。

否則我可以有與所有列相同的模型,並只提取所需的(其他人將是零課程)。

UPDATE 在用戶表中使用role和integer,然後使用枚舉。 我正在使用Rails 5和devise 4.3.0。

+0

您可以輕鬆地使用'enum'單表繼承適應當前的角色。 –

回答

4

你可能想看看單表繼承

嘗試DeveloperDriver,無論從User繼承和共享一個users數據庫表。每個實際上都是它自己的模型,允許你定義完全獨立的關聯,回調,驗證,實例方法等......

它們共享所有相同的數據庫列,並且User類中定義的任何內容都將被繼承並可以被覆蓋)。您需要將type列添加到users。所有的DeveloperDriver列字段也應該爲users表定義。

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 

您還可以使用enumtype列,覆蓋默認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

@Jonathan足夠公平,改進了答案。感謝您的反饋 –

+0

非常棒的工作!我只是刪除我的國旗。 – Jonathan

+0

謝謝!這裏還是新的:) –

0

那麼這兩個辦法可以解決你的問題。我個人只會有一個表,因爲Developer也是類型UserDriver也是User類型。你可以這樣做:

class User < ActiveRecord::Base 
end 

class Developer < User 
end 

class Driver < User 
end 

如果用戶是開發者,那麼你可以爲開發者提取額外的列。沒有任何價值的列很少。

+0

謝謝,通過這樣做,我將能夠驗證我需要什麼。 –

0

您可以根據不同列的數量來決定。如果不同列的數量更多,這似乎是這種情況,創建一個包含所有公共列和另外2個表(開發人員和驅動程序)的用戶表,其中將包含user_id以與用戶進行映射。

也創建一個名爲角色的表。角色將包含id和role_name(驅動程序,開發人員等)並在用戶表中添加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

+0

謝謝。這會花費在db查詢中。單表繼承似乎是更健壯的解決方案。 –

+0

是的,我同意這一點,但如果你想在將來增加更多的角色,你最終會浪費很多空間,因爲空列很多(很多空列)。如果你沒有很多不同的列或更多的角色,那麼你可以繼續單表繼承。 –

相關問題