我正在尝试打开注册页面以创建一个帐户(有付款),并且出现此错误“ Account:Class的未定义方法'has_one'”。我没有使用数据库,所以没有使用活动记录。有没有解决的办法?
account.rb
class Account
include ActiveModel::Model
attr_accessor :company_name, :phone_number,
:card_number, :expiration_month, :expiration_year, :cvv
has_one :payment
end
payment.rb
class Payment
include ActiveModel::Model
attr_accessor :card_number, :expiration_month, :expiration_year, :cvv
belongs_to :account
validates :card_number, presence: true, allow_blank: false
validates :cvv, presence: true, allow_blank: false
end
account_controller.rb
class AccountController < ApplicationController
def register
@account = Account.new
end
end
has_one
和belongs_to
不属于ActiveModel::Model
。它们是ActiveRecord
的一部分,因为它们指定如何从关系数据库中获取对象。
在您的情况下,我想您应该只在payment
模型中具有另一个属性Account
。
class Account
include ActiveModel::Model
attr_accessor :company_name, :phone_number,
:card_number, :expiration_month,
:expiration_year, :cvv,
:payment
end
然后在您的控制器中执行类似的操作
class AccountController < ApplicationController
def register
@account = Account.new
@account.payment = Payment.new
end
end
或者您可以在Account
类的初始值设定项中初始化付款。同样,似乎Payment
不需要了解Account
。
无疑,这是一个非常老的问题,但是我在尝试解决类似问题时遇到了这个问题,最终发现在随后的几年中已经出现了解决方案。因此,鉴于唯一发布的答案从未被标记为“已接受”,所以我想把帽子戴在戒指里。
Rails 5引入了ActiveRecord Attributes API,通过this post by Karol Galanciak describing it,您可能有兴趣查看gem created by the same author。如果您查看了该gem的问题,则可能有兴趣在issue #12中阅读ActiveModel中现在具有Attributes API功能,尽管该功能尚未公开记录(module Attributes
标记为#:nodoc:
,请参见attributes.rb),并且也许不应该依赖于各个版本之间的一致性,尽管有时似乎似乎有些软绵绵的风向着“公共”ActiveModel::Attributes
API的方向发展。
但是,如果您要谨慎对待并使用不太公开的ActiveModel::Attributes
,则可以执行以下操作(请注意:我将其拼凑成自己的项目,并对其进行了重新编写以适合您的示例,您的需求可能与我的不同):
class AccountPayment
include ActiveModel::Model
attr_accessor :card_number, :expiration_month, :expiration_year, :cvv
validates :card_number, presence: true, allow_blank: false
validates :cvv, presence: true, allow_blank: false
end
class AccountPaymentType < ActiveModel::Type::Value
def cast(value)
AccountPayment.new(value)
end
end
class Account
include ActiveModel::Model
include ActiveModel::Attributes #being bad and using private API!
attr_accessor :company_name, :phone_number, :card_number, :expiration_month, :expiration_year, :cvv
attribute :payment, :account_payment
end
并且您必须在某个位置注册该类型-在rails中它将在初始化程序中,但是在我的代码中,我只是将其保存在与Account
模型等效的顶部:]
ActiveModel::Type.register(:account_payment, AccountPaymentType)