繁体   English   中英

在 rails 6 上未触发 before_save 回调

[英]before_save callback is not being triggered on rails 6

在运行测试时:

require 'rails_helper'

RSpec.describe DailyTask, type: :model do
  context 'crud' do
    [...]
  end

  context 'validations' do
    let(:task) { create(:task) }

    it 'duplicated task, fails' do
      2.times do
        DailyTask.create(task: task, date: Date.today) 
      end
      expect(DailyTask.count).to eq(1)
    end
  end
end

将触发before_save回调,如下所示:

class DailyTask < ApplicationRecord
  belongs_to :task

  validates_presence_of :date

  before_save :is_there_a?

  def is_there_a?
    DailyTask.where(date: self.date, task_id: self.task_id).empty?
  end
end

然而,它似乎没有被触发。 已经尝试将其更改为before_validation无济于事。 这是一种愚蠢的错误,除非有人指出,否则您不会看到。

编辑:在调用before_validation地方粘贴了旧版本的代码。

before_save回调调用。 (尝试在方法中添加调试器,然后看看!)但它并没有按照您的意愿行事 - 您的代码中存在错误。

要修复代码,如果检查失败,您需要添加验证错误 (您当前的方法只是检查任务是否存在;它实际上并没有对这些信息做任何事情。)

你可以这样写:

validate :is_there_a?

def is_there_a?
  if DailyTask.where(date: self.date, task_id: self.task_id).any?
    errors.add(:date, 'already exists for this task')
  end
end

或者,您可以只使用 Rails 的内置唯一性验证方法其范围为

validate_uniqueness_of :date, scope: :task_id

或者,如果您愿意,也可以将两个验证规则合并到一行代码中:

validates :date, presence: true, uniqueness: { scope: :task_id }

作为一个单独的建议,我个人会以稍微不同的方式编写这个测试。 代替:

it 'duplicated task, fails' do
  2.times do
    DailyTask.create(task: task, date: Date.today) 
  end
  expect(DailyTask.count).to eq(1)
end

您可以考虑编写它以更明确地测试验证:

it 'duplicated task, fails' do
  DailyTask.create(task: task, date: Date.today)
  duplicate_daily_task = DailyTask.new(task: task, date: Date.today)
  expect(duplicate_daily_task).not_to be_valid
end

然后,您还可以验证为什么重复任务被视为“无效”。 此外,您可能希望考虑使用工厂来创建记录,而不是直接使用 rails 类。

暂无
暂无

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

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