Rails - проверка проверки полей enum

Я использую Rails 4 enums, и я хочу их правильно протестировать, поэтому я установил эти тесты для своих полей enum:

it { should validate_inclusion_of(:category).in_array(%w[sale sale_with_tax fees lease tax_free other payroll]) }
it { should validate_inclusion_of(:type).in_array(%w[receivable payable]) }

И это модель, которую они проверяют:

class Invoice < ActiveRecord::Base
  belongs_to :user

  enum category: [:sale, :sale_with_tax, :fees, :lease, :tax_free, :other, :payroll]
  enum type: [:receivable, :payable]

  validates :user, presence: true
  validates :issue_date, presence: true
  validates :series, presence: true
  validates :folio, presence: true
  validates :issuing_location, presence: true
  validates :payment_method, presence: true
  validates :last_digits, presence: true
  validates :credit_note, presence: true
  validates :total, presence: true
  validates :subtotal, presence: true
  validates :category, presence: true
  validates_inclusion_of :category, in: Invoice.categories.keys
  validates :type, presence: true
  validates_inclusion_of :type, in: Invoice.types.keys
end

Но когда я запускаю тесты, я получаю:

1) Invoice should ensure inclusion of type in [0, 1]
     Failure/Error: it { should validate_inclusion_of(:type).in_array([0,1]) }
     ArgumentError:
       '123456789' is not a valid type
     # ./spec/models/invoice_spec.rb:20:in `block (2 levels) in <top (required)>'

  2) Invoice should ensure inclusion of category in [0, 1, 2, 3, 4, 5, 6]
     Failure/Error: it { should validate_inclusion_of(:category).in_array([0,1,2,3,4,5,6]) }
     ArgumentError:
       '123456789' is not a valid category
     # ./spec/models/invoice_spec.rb:19:in `block (2 levels) in <top (required)>'

Я также пытался использовать строковые значения в тестовых массивах, но я получаю ту же ошибку, и я действительно не понимаю ее.

Ответ 1

С помощью контролеров Shoulda мы можем использовать следующее для проверки перечисления

it { should define_enum_for(:type).with([:receivable, :payable]) }

it { should define_enum_for(:category).
            with(:sale, :sale_with_tax, :fees, :lease, :tax_free, :other, :payroll) }

Ответ 2

Попробуйте следующее:

it { should validate_inclusion_of(:category).in_array(%w[sale sale_with_tax fees lease tax_free other payroll].map(&:to_sym)) }

Кроме того, для очистки кода попробуйте поместить действительные категории/типы в соответствующую константу. Пример:

class Invoice < ActiveRecord::Base
  INVOICE_CATEGORIES = [:sale, :sale_with_tax, :fees, :lease, :tax_free, :other, :payroll]
  enum category: INVOICE_CATEGORIES
end

Ответ 3

Ваша миграция может быть проблемой, она должна выглядеть примерно так:

t.integer :type, default: 1

Вы также можете рассмотреть возможность проверки этого другого способа.

Возможно, больше нравится:

it "validates the category" do
  expect(invoice with category fee).to be_valid
end

Ответ 4

У вас есть эта строка в ваших проверках:

validates_inclusion_of :category, in: Invoice.categories.keys

в случае перечисления Invoice.categories.keys # = > [ "sale", "sale_with_tax", "fee", "lease", "tax_free", "other", "payroll" ]

Вы должны обновить данные своего объекта одним из имен вашего перечисления.

Ответ 5

Просто используйте спички:

it { should define_enum_for(:type).with_values([:receivable, :payable]) }

it { should define_enum_for(:category).with_values(:sale, :sale_with_tax, :fees, :lease, :tax_free, :other, :payroll)}