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

问题描述 投票:0回答:2

我正在尝试打开注册页面以创建一个帐户(有付款),并且出现此错误“ 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
ruby-on-rails associations
2个回答
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


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::AttributesAPI的方向发展。

但是,如果您要谨慎对待并使用不太公开的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)
© www.soinside.com 2019 - 2024. All rights reserved.