繁体   English   中英

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

[英]Using rails associations for models (undefined method `has_one')

我正在尝试打开注册页面以创建一个帐户(其中有付款),但出现此错误“Account:Class 的未定义方法‘has_one’”。 我没有使用数据库,所以我没有使用活动记录。 有没有解决的办法?

账号.rb

class Account
    include ActiveModel::Model

    attr_accessor :company_name, :phone_number,
                            :card_number, :expiration_month, :expiration_year, :cvv

    has_one :payment
end

付款.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_onebelongs_to不是ActiveModel::Model一部分。 它们是ActiveRecord一部分,因为它们指定了如何从关系数据库中获取对象。

在您的情况下,我想您应该在Account模型中有另一个属性payment

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, 通过 Karol Galanciak这篇文章描述它,您可能有兴趣看一看由同一作者创建gem 如果您查看了该 gem 的问题,您可能有兴趣阅读issue #12中的 Attributes API 功能现在存在于 ActiveModel 中,尽管它没有公开记录( module Attributes被标记为#:nodoc: ,请参阅attributes.rb ) 并且也许不应该依赖于版本与版本之间的一致性,尽管有时看起来很柔和的风肯定是朝着“公共” ActiveModel::Attributes的方向吹的应用程序接口。

尽管如此,如果您要谨慎行事并使用不完全公开的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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM