在设计数据模型时,您有时会找到一个与自身有关系的模型。 Ruby On Rails Guide provides a neat example。我使用它作为我的例子的模板
例如,您可能希望将所有users
存储在单个数据库模型中,但能够跟踪affiliate
和users
之间的关系。这种情况可以通过自联合协会建模:
class User < ApplicationRecord
has_many :users, :through => :referrals
has_one :affiliate, :through => :referral
end
这允许我将users
和affiliate
保存在同一个数据库表中,这是正确的,因为从根本上说它们都是个人用户。
模型增长时出现问题。 Affiliate
有自己的一套方法 - earnings
,expected_earnings
等。这些方法非常具体针对Affiliate
而且我有理由将它们与其他user
保持一致方法
在正确命名的变量中加载对象有助于:
affiliate = User.find 1
affiliate.earnings # used in context of affiliate
user = User.find 1
user.subscriptions # mostly in context to user
但是,当我阅读User
模型时,Affiliate
相关方法感觉不合适。
有没有办法正确命名这些方法?组织自联接模型方法的标准方法是什么?
答案 0 :(得分:0)
解决此问题的一种方法是使用Single Table Inheritance。在接受这种方法之前,我建议在网上搜索&#34;单表继承轨道&#34;并阅读它的利弊。在这个主题上花了很多数字墨水。
有了警告,单表继承(STI)允许您让多个Rails模型共享一个数据库表。您可以通过向数据库表中添加名为string
的{{1}}字段来执行此操作。 Rails会将此解释为模型的子类。然后,您将创建几个继承自type
的模型。
在您的具体情况下,User
字段可能包含type
或user
。您还将创建一个继承自affiliate
的{{1}}类。您的所有Affliliate
具体方法都将放在User
类中。 Rails足够聪明,可以使用数据库中的Affiliate
字段来识别相应类中的记录。
以下是您要运行的迁移:
Affiliate
接下来,您将添加一个Affiliate类:
type
您可能还想为非联盟用户创建一个班级。称之为客户:
class AddTypeToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :type, :string
add_index :users, :type
end
end
在创建新记录时使用适当的类名,rails将自动填充数据库中的# app/models/affliliate.rb
class Affiliate < User
# Affiliate specific methods here.
end
字段。
然后,您可以将关联移动到适当的模型:
# app/models/customer.rb
class Customer < User
# Customer specific methods here.
end
我没有对此进行过测试,但它应该有效。