如何在自联接模型中组织方法

时间:2017-10-31 13:17:23

标签: ruby-on-rails

在设计数据模型时,您有时会找到一个与自身有关系的模型。 Ruby On Rails Guide provides a neat example。我使用它作为我的例子的模板

例如,您可能希望将所有users存储在单个数据库模型中,但能够跟踪affiliateusers之间的关系。这种情况可以通过自联合协会建模:

class User < ApplicationRecord
    has_many :users, :through => :referrals
    has_one :affiliate, :through => :referral
end

这允许我将usersaffiliate保存在同一个数据库表中,这是正确的,因为从根本上说它们都是个人用户。

模型增长时出现问题。 Affiliate有自己的一套方法 - earningsexpected_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相关方法感觉不合适。

有没有办法正确命名这些方法?组织自联接模型方法的标准方法是什么?

1 个答案:

答案 0 :(得分:0)

解决此问题的一种方法是使用Single Table Inheritance。在接受这种方法之前,我建议在网上搜索&#34;单表继承轨道&#34;并阅读它的利弊。在这个主题上花了很多数字墨水。

有了警告,单表继承(STI)允许您让多个Rails模型共享一个数据库表。您可以通过向数据库表中添加名为string的{​​{1}}字段来执行此操作。 Rails会将此解释为模型的子类。然后,您将创建几个继承自type的模型。

在您的具体情况下,User字段可能包含typeuser。您还将创建一个继承自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

我没有对此进行过测试,但它应该有效。