Общие проверки модели Rails, унаследованные от абстрактного базового класса, но уникальные проверки полей происходят на подклассе - PullRequest
0 голосов
/ 16 января 2020

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

Существует два класса позиций счетов-фактур: продажи и коллекции. Эти позиции имеют общее поле invoice_amount Я хочу проверить наличие invoice_amount из абстрактного базового класса, но подклассы проверяют поля, которые не являются общими для обеих моделей.

class Collection < InvoiceLineItem
  belongs_to :invoice
  validates :c_number, :invoice_number, :invoice_date, presence: true
.
.
.
end
class Sale < InvoiceLineItem
  belongs_to :invoice
.
.
.
end
class InvoiceLineItem < ApplicationRecord
  self.abstract_class = true

  def self.inherited(base)
    super
    base.send(:extend, NumberFormatter)
    base.send(:commafy, :invoice_amount)
  end

  def invoice_amount
    self[:invoice_amount] || '0.00'
  end

  def export_date
    invoice_date
  end
end

Я пробовал несколько вещей, чтобы заставить это работать безуспешно. Некоторые из моих попыток включали добавление следующего кода в базовый класс InvoiceLineItem

  def self.inherited(base)
    base.class_eval do
      validates :invoice_amount, presence: true
    end
    super
    base.send(:extend, NumberFormatter)
    base.send(:commafy, :invoice_amount)
  end

и

  def self.inherited(base)
    base.class_eval do
      base.send(:validates, :invoice_amount, presence: true)
    end
    super
    base.send(:extend, NumberFormatter)
    base.send(:commafy, :invoice_amount)
  end

, и это, как описано здесь (https://medium.com/@jeremy_96642 / deep-rails- how-to-use-abstract-classes-6aee9b686e75 ), что выглядело многообещающе, потому что оно точно описывало, что я хочу сделать, однако это не работает для меня.

   with_options presence:true do
     validates :invoice_amount
   end

Во всех этих случаях код выполняется без ошибок, однако, если я напишу тест, как показано ниже, он завершится неудачно, потому что проверка прошла успешно!

RSpec.describe Collection, type: :model do
  it "Requires an invoice amount" do
    result = Collection.create(invoice_amount: nil, c_number: 'CUST012', invoice_number: 'INV001', invoice_date: Date.new(1999, 1,1))
    expect(result.valid?).to be false
    expect(result.errors[:invoice_amount]).to include("can't be blank")
  end
end

Мне не очень интересно слышать ответы о том, как это должно быть сделано с использованием композиции вместо наследования. Я не буду go в детали, но просто предположим, что это должно быть сделано с использованием наследования. Кажется, что это должно быть возможно, но я не уверен, и я не могу найти источник на inte rnet, который имеет решение, которое действительно работает.

Любая помощь будет принята с благодарностью!

1 Ответ

0 голосов
/ 16 января 2020

Я выяснил свою проблему, оказалось, что этот код работал:

class InvoiceLineItem < ApplicationRecord
  self.abstract_class = true

  def self.inherited(base)
    super
    base.send(:extend, NumberFormatter)
    base.send(:commafy, :invoice_amount)
  end

  with_options presence: true do
    validates :invoice_amount
  end

  def invoice_amount
    self[:invoice_amount] || 0.00
  end

  def export_date
    invoice_date
  end

  def debtor_number_up_to_space
    debtor_number.split[0]
  end
end

валидатор использовал метод invoice_amount, который скрывал поле в модели, поэтому invoice_amount не было видно как nil, но как 0.00, таким образом, проверка моего теста прошла успешно.

Как только я удалил || 0.00, я мог получить тест на неудачу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...