对模型使用rails关联(未定义的方法`has_one')

时间:2015-02-10 15:46:33

标签: ruby-on-rails associations

我正在尝试打开注册页面来创建一个帐户(有付款),我收到了这个错误"未定义的方法`has_one'帐户:Class"。我没有使用数据库,所以我没有使用活动记录。有办法解决这个问题吗?

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

2 个答案:

答案 0 :(得分:0)

has_onebelongs_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

答案 1 :(得分:0)

当然,这是一个非常老的问题,但是我在尝试解决类似问题时遇到了这个问题,最终发现在随后的几年中出现了解决方案。因此,鉴于唯一发布的答案从未被标记为“已接受”,所以我想把帽子戴在戒指里。

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)