单表继承
什么是单表继承
Single Table Inheritance (separate classes, one table) 单表继承就是一张表, 分多个类使用。
何时使用单表继承
当各个模型之间只有细微的差别时,在使用前首先要问自己几个问题:
- 是所有的对象都继承自一个类吗?
- 是否需要对数据库中的所有对象进行查询操作?
- 是所有对象都有相同的属性,但是不同的行为吗?
如果你要跨子类进行查询,那么毫无疑问要用 STI。
具体实现
rails g migration add_type_to_users type
rails g migration remove_guest_from_users guest:boolean
rake db:migrate
class User < ActiveRecord::Base
has_many :tasks, dependent: :destroy
def guest?
raise NotImplementError, "Must be implemented in subclasses."
end
#etc...
end
class Guest < User
def guest?
true
end
def move_to(user)
tasks.update_all(user_id: user.id)
end
def name
"Guest"
end
def task_limit
10
end
def can_share_task?(task)
false
end
def send_password_reset
end
end
class Member < User
attr_accessor :username, :email, :password, :password_confirmation
validates_presence_of :username, :email
validates_uniqueness_of :username, allow_blank: true
has_secure_password
def guest?
false
end
def name
username
end
def task_limit
1000
end
def can_share_task?(task)
task.user_id == id
end
def send_password_reset
UserMailer.password_reset(self).deliver
end
end
使用多态来替换 STI
# Suppose the AccountHolder parent class is used
# to simply have an association with an account so
# both corporations and people can have accounts.
class Account < ActiveRecord::Base
belongs_to :account_holder
end
class AccountHolder < ActiveRecord::Base
has_one :account
end
class Corporation < AccountHolder
end
class Person < AccountHolder
end
# Just use a polymorphic association instead
class Account < ActiveRecord::Base
belongs_to :account_holdable, polymorphic: true
end
class Corporation < AccountHolder
has_one :account, as: :account_holdable
end
class Person < AccountHolder
has_one :account, as: :account_holdable
end
# As such, accounts would need the polymorphic columns
# `account_holdable_type` and `account_holdable_id` which
# would describe the class as well as the primary key, respectively.
class CreateAccounts < ActiveRecord::Migration[5.0]
def change
create_table :accounts do |t|
# ... various fields
t.integer :account_holdable_id
t.string :account_holdable_type
t.timestamps
end
end
end
相关阅读