解决多表继承的最佳方法

时间:2017-03-09 18:44:44

标签: ruby-on-rails postgresql activerecord

好的,所以我有一个关于如何最好地解决rails问题的问题。我将展示我是如何解决它的,但我真的希望得到一些关于这种方法的反馈,以及是否有更好的事情要做。

首先,我有一个基本的电子商务应用程序,包括客户,付款方式和付款。

现在付款方式可以是几种不同的类型,EG'Stripe,Braintree,Paypal'。这些都是付款方式,但它们具有非常不同的逻辑来处理它们的工作。

理想情况下,我希望能够致电customer.payment_methods并获得付款方式的关系。我还希望能够拨打customer.stripe_payment_methods并获取Stripe方法。

我最初想过使用和STI模型,但这似乎效率低下,因为每种付款方式都有不同的列。

必须在表格中存储类型字段似乎很浪费。

以下是相关模型

class PaymentMethod
    scope :stripe, -> {where(type: 'PaymentMethod::Stripe')}
    scope :paypal, -> {where(type: 'PaymentMethod::Paypal')}

    # Lists available payment types
    def self.available_types
        PaymentMethod.subclasses.map { |d| [d::NAME, d.to_s] }
    end
end

class PaymentMethod::Stripe < PaymentMethod
    #performs Stripe specific methods
end

class PaymentMethod::Paypal < PaymentMethod
    #performs Paypal specific actions.
end

这些都使用payment_methods表。这可以按照我的意图运作,但感觉很草率。

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

你真的不需要范围。

PaymentMethod.all         # will get you all payments of any type
PaymentMethod::Stripe.all # will get you only the records using Stripe
PaymentMethod::Paypal.all # will get you only records using Paypal

由于额外的字段,这并不总是理想的。您有几个选择:

1)与重复一起生活。大多数数据库非常有效,并且不会浪费太多空间。问题更多的是在代码中错误地使用它们。

2)使用通用字段名称并在子类中添加方法以转换为更好的字段名称

3)使用JSON字段类型并在子类中添加方法以简化访问

4)将特定于Stripe的字段分成第二个表,将特定于Paypal的字段分成第三个表。然后,您将拥有Payment has_one :tripe关系。缺点是使用变得更加困难(尽管您可以通过委派来缓解这种情况),更重要的是,您需要小心多个查询和/或连接的性能损失。