首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用抽象类在Rails中表示has_many关系

使用抽象类在Rails中表示has_many关系
EN

Stack Overflow用户
提问于 2018-05-31 16:25:13
回答 1查看 464关注 0票数 0

我有一段很难模型化的关系。

我有一个Subscription类,它是一个常规的ActiveRecord模型,它可以有一个或多个PaymentSources。然而,问题是支付源可以指CreditCardBankAccount

考虑到这些模型具有非常不同的相关数据,我认为STI在这里不是一个好的选择。所以我想知道,对于Rails中另一个模型的模型has_many实际上是2个或更多不共享相同数据布局的类的抽象,是否有一种既定的或推荐的方法。

理想情况下,在这个特定的示例中,我可以说类似subscription.payment_source.default的内容,并根据用户选择的首选计费方法来引用CreditCardBankAccount

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-31 16:55:00

TLDR:

经过深思熟虑后更新,我将选择选项2(更完整的解决方案),它是面向未来的灵活的,但如果您不需要所有这些复杂性,我将只使用选项1。

选项1:

代码语言:javascript
复制
class Subscription < ApplicationRecord
  belongs_to :credit_card
  belongs_to :bank_account

  def payment_sources
    [credit_card, bank_account].compact
  end

  def default_payment_source
    case user.preferred_billing_method # assuming you have an integer column in users table called `preferred_billing_method`
    when 0 then credit_card # asssuming 0 means "Credit Card"
    when 1 then bank_account # assuming 1 means "Bank Account"
    else NotImplementedError
    end
  end
end

用法

代码语言:javascript
复制
Subscription.first.default_payment_source
# => returns either `CreditCard` or `BankAccount`, or `nil`

Subscription.first.payment_sources.first
# => returns either `CreditCard` or `BankAccount`, or `nil`

选项2:

代码语言:javascript
复制
class User < ApplicationRecord
  belongs_to :default_payment_source, class_name: 'PaymentSource'
  has_many :subscriptions
end

class Subscription < ApplicationRecord
  belongs_to :user
  has_many :payment_sources_subscriptions
  has_many :payment_sources, through: :payment_sources_subscriptions
end

# This is just a join-model
class PaymentSourcesSubscription < ApplicationRecord
  belongs_to :subscription
  belongs_to :payment_source

  validates :subscription, uniqueness: { scope: :payment_source }
end

# this is your "abstract" model for "payment sources"
class PaymentSource < ApplicationRecord
  belongs_to :payment_sourceable, polymorphic: true
  has_many :payment_sources_subscriptions
  has_many :subscriptions, through: :payment_sources_subscriptions

  validates :payment_sourceable, uniqueness: true
end

class CreditCard < ApplicationRecord
  has_one :payment_source, as: :payment_sourceable
end

class BankAccount < ApplicationRecord
  has_one :payment_source, as: :payment_sourceable
end

用法:

代码语言:javascript
复制
User.first.default_payment_source.payment_sourceable
# => returns either `CreditCard` or `BankAccount`, or `nil`

Subscription.first.payment_sources.first.payment_sourceable
# => returns either `CreditCard` or `BankAccount`, or `nil`
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50619853

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档