我有一个Contract
模型,每个模型有两个Payment
(prepayment
和second_payment
)。
我知道一种可行的方法可能如下:
class Contract < ActiveRecord::Base
belongs_to :prepayment, :class_name => "Payment"
belongs_to :second_payment, :class_name => "Payment"
end
## Schema
create_table "contracts" do |t|
t.integer "prepayment_id"
t.integer "second_payment_id"
end
但从逻辑上讲,对于属于contract
的{{1}}或者payment
有合同,这听起来不合适。应该反过来。
建立这种关系的最佳做法是什么?
答案 0 :(得分:1)
我宁愿使用支付模式关联正常,也可以在支付中添加一个类别,“预付款”可以是0,“付款”可以是1。通过这种方式,您可以通过添加其他类别来进行其他类型的付款,并且您不需要每次都修改关联。
class Contract < ActiveRecord::Base
has_many :payments
end
class Payment < ActiveRecord::Base
enum category: [ :payment, :prepayment ]
end
## Schema
create_table "prepayment" do |t|
t.integer "category"
end
答案 1 :(得分:0)
逻辑方法是使用这个(简单实现):
class Contract < ActiveRecord::Base
has_many :payment_transactions, as: :transactionable
end
class PaymentTransaction < ActiveRecord::Base
belongs_to :transactionable, polymorphic: true
end
对于PaymentTransaction,您可以使用枚举字段:
enum payment_type: [:first_income, :expense]
答案 2 :(得分:0)
我这样做:
#app/models/contract.rb
class Contract < ActiveRecord::Base
has_many :payments, -> { where(category: [0,1]) } #-> only returns the payments where category is "prepayment" or "secondary_payment"
end
#app/models/payment.rb
class Payment < ActiveRecord::Base
belongs_to :contract
enum category: [:prepayment, :secondary_payment]
validates :category, uniqueness: { scope: :contract_id } #-> only one of each category per contract
scope :pre, -> { find_by category: 0 }
scope :secondary, -> { find_by category: 1 }
end
这样,您就可以使用以下内容:
@contract = Contract.find(1)
@contract.payments.pre
@contract.payments.secondary