2017-03-09 9 views
0

OK, also habe ich eine Frage darüber, wie man am besten ein Problem in Schienen löst. Ich werde zeigen, wie ich es gelöst habe, würde aber gerne ein Feedback zu diesem Ansatz haben und ob es etwas Besseres zu tun gibt.Beste Möglichkeit, Multi Table Vererbung zu lösen

Zu Beginn habe ich eine grundlegende E-Commerce-App mit Kunden, Zahlungsmethoden und Zahlungen.

Jetzt kann eine Zahlungsmethode von verschiedenen Arten sein, EG 'Streifen, Braintree, Paypal'. Dies sind alle Zahlungsmethoden, aber sie haben eine sehr unterschiedliche Logik, um mit dem umzugehen, was sie tun.

Idealerweise möchte ich customer.payment_methods anrufen und eine Beziehung der Zahlungsmethoden erhalten. Ich möchte auch customer.stripe_payment_methods anrufen können und nur die Stripe-Methoden bekommen.

Ich dachte ursprünglich an die Verwendung und STI-Modell, aber das scheint ineffizient, da jede Zahlungsmethode unterschiedliche Spalten hat, auf die es ankommt.

Es erscheint verschwenderisch, ein Typfeld in der Tabelle speichern zu müssen.

Hier sind die relevanten Modelle

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 

Diese verwenden alle die payment_methods Tabelle. Das funktioniert so, wie ich es mir vorgestellt habe, aber es fühlt sich schlampig an.

Gibt es einen besseren Weg, dies zu tun?

Antwort

1

Sie brauchen die Bereiche nicht wirklich.

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 

Dies ist nicht immer ideal wegen der zusätzlichen Felder. Sie haben ein paar Optionen:

1) Live mit der Duplizierung. Die meisten Datenbanken sind ziemlich effizient und es wird nicht viel Platz verschwenden. Das Problem besteht eher darin, sie fälschlicherweise im Code zu verwenden. zu vereinfachen Zugang

4)

2) generische Feldnamen verwenden und Methoden in der Unterklasse in den schöneren Feldnamen

3) Verwenden Sie einen JSON Feldtyp und fügen Sie Methoden in der Unterklasse zu übersetzen Trennen Sie die Stripe-spezifischen Felder in eine zweite Tabelle und die für Paypal spezifischen Felder in eine dritte Tabelle. Sie haben dann eine Payment has_one :tripe Beziehung. Der Nachteil ist, dass die Verwendung schwieriger wird (obwohl Sie dies durch Delegierung abschwächen können), was noch wichtiger ist, Sie müssen vorsichtig mit der Leistungserfüllung von mehreren Abfragen und/oder Joins sein.

Verwandte Themen