Techioz Blog

Railsでテストを実行する際の未定義のメソッド

概要

そこで、プログラムのテストを作成して実行したいと考えています。 bin/rails テスト test/models/inventory_test.rb

エラーが発生する

# Running:

E

Error:
InventoryTest#test_quantity_should_not_be_negative:
NoMethodError: undefined method `variations' for #<#<Class:0x000000010862c9e8>:0x000000010864a290>
    test/fixtures/inventories.yml:2:in `get_binding'

ここで、モデルに基づいてフィクスチャを作成しました。inventories.yml は次のようになります。


one:
  variation_id: <%= variations(:one) %>
  warehouse_id: <%= warehouses(:one) %>
  quantity: 50
  updated_by_user_id: <%= users(:one) %>
  product_id: <%= products(:one) %>
  created_at: <%= fake_time %>
  updated_at: <%= fake_time %>

two:
  variation_id: <%= variations(:two) %>
  warehouse_id: <%= warehouses(:two) %>
  quantity: 100
  updated_by_user_id: <%= users(:two) %>
  product_id: <%= products(:two) %>
  created_at: <%= fake_time %>
  updated_at: <%= fake_time %>


なぜバリエーションメソッドを取得しようとするのかわかりません。私はバリエーションメソッドを持っていませんし、これをデバッグする方法もわかりません。あらゆることを試しました。

私のインベントリモデルは次のようになります。

class Inventory < ApplicationRecord
  belongs_to :product
  belongs_to :warehouse
  belongs_to :variation
  belongs_to :updated_by, class_name: "User", foreign_key: "updated_by_user_id"

  has_many :inventory_transactions

  validates :quantity, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
  has_one :restock_alert, dependent: :destroy
  after_save :check_restock_alert

  def check_restock_alert
    if self.quantity <= self.restock_alert.threshold
      self.restock_alert.update(status: RestockAlert::TRIGGERED)
    elsif self.quantity > self.restock_alert.threshold
      self.restock_alert.update(status: RestockAlert::PENDING)
    end
  end
  
end



他のフィクスチャでvariation_id: oneなどを作成しようとすると、他の問題が発生します。 これは私が解決策に最も近いように感じますが、私が持っていないバリエーションメソッドをチェックします。

解決策

inventories.yml ファイルで .erb 構文が必要ないため、なぜそれを使用しているのかわかりません。フィクスチャでは、それほど多くの作業を行わなくても、関連付けを介して相互に参照するレコードを作成できます。したがって、次のファイルがあるとします。

one:
  variation_id: <%= variations(:one) %>
  warehouse_id: <%= warehouses(:one) %>
  quantity: 50
  updated_by_user_id: <%= users(:one) %>
  product_id: <%= products(:one) %>
  created_at: <%= fake_time %>
  updated_at: <%= fake_time %>

次のようなvariations.ymlがある場合:

one:
   foo: bar
   ...

これを行う必要があるのは、inventory.yml 内だけです。

one:
  variation: one
  warehouse: one #assumes a warehouses.yml with a record with that name
  quantity: 50
  updated_by_user: one
  product: one
  created_at: <%= fake_time %>
  updated_at: <%= fake_time %>