我有一个名为PaypalPayment
的模型:
class PaypalPayment < PaymentMethod
belongs_to :order
def provider_class
PaypalPayment
end
def process!
end
end
我为它生成了以下迁移:
class CreatePaypalPayments < ActiveRecord::Migration
def change
create_table :paypal_payments do |t|
t.integer :order_id
t.integer :payment_id
t.timestamps
end
end
end
和
class AddDetailsToPaypalPayment < ActiveRecord::Migration
def change
add_column :paypal_payments, :state, :string
add_column :paypal_payments, :amount, :decimal
add_column :paypal_payments, :cc, :string
add_column :paypal_payments, :cm, :string
end
end
迁移后,表格如下所示:
development_database=# select * from paypal_payments;
id | order_id | payment_id | created_at | updated_at | state | amount | cc | cm
但是当我尝试初始化此模型的对象时,我得到的是unknown attribute: payment_id
。
@paypal_payment = PaypalPayment.new(:payment_id => params[:tx], :state => params[:st], :cc => params[:cc], :cm => params[:cm], :order_id => params[:id])
编辑: db / schema.rb:
create_table "paypal_payments", :force => true do |t|
t.integer "order_id"
t.integer "payment_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "state"
t.decimal "amount"
t.string "cc"
t.string "cm"
end
答案 0 :(得分:2)
在关系数据库中有不同的模型继承方法,Martin Fowler列出了以下选项:
PaymentMethod
如果是抽象的,就没有表)现在ActiveRecord only supports STI:单表继承。
所以,如果你写
class PaypalPayment < PaymentMethod
ActiveRecord将假设STI并查找类型列,此外,只会查找payment_methods
表。
根据您的需求,在大多数情况下,STI是完美的。有时我更喜欢Class和Concrete Table Inheritance,但特别是对于关联,这需要更多的家庭住宅,因为:
有很多方法可以解决这个问题,但总是比使用单个表更难。这也是拉伸关系数据模型,因为根据所选择的解决方案,不会自动支持外键约束。我可以详细介绍一下 但我不确定这是否相关,因为你的例子似乎是STI的经典案例。
如果你想使用类表继承或具体表继承,每个类必须派生自`ActiveRecord :: Base``,如果需要,你应该包含一个带有共享行为的模块(或关注点)(因为ruby确实如此)不支持多重继承)。
答案 1 :(得分:1)
我相信你必须在“PaymentMethods”表中添加“type”列。这将允许它是可继承的。没有类型列,当您实例化PaypalPayment时,它认为它是一个PaymentMethod,因此没有PaypalPayment的唯一字段。但是,当您将“type”列添加到PaymentMethod时,它将存储“PaypalPayment”,ActiveRecord知道使PaypalPayment方法可用。你应该为PaymentMethod创建一个模型,并确保它继承ActiveRecord :: Base
def change
add_column :payment_methods, :type, :string
end
答案 2 :(得分:0)
我会这样做:
检查您的Rails控制台 -
$ rails c
$ payment = PaypalPayment.find(1)
$ payment.column_names #-> should reveal which columns Rails comes back with
检查Rails正在拾取属性
为了测试,请尝试attr_accessor :payment_id
查看是否有效。您可能没有在模型中允许该属性
在Rails4中,这意味着使用strong params
,但在Rails 3中,我认为这意味着使用attr_accessible
这样:
#app/models/paypal_payment.rb
Class PaypalPayment < ActiveRecord::Base
attr_accessible :payment_id #-> tests parameter passing
attr_accessor :payment_id #-> tests virtual attribute assignment
end
答案 3 :(得分:0)
我知道我这里的节目有点迟了,但是如果有人遇到类似Rails 5.1的问题,在我的情况下,我能够通过在我的父类中包含以下行来解决问题
self.abstract_class = true