【问题标题】:Custom Validation Check自定义验证检查
【发布时间】:2016-05-16 06:54:27
【问题描述】:

我有以下休假模型。我要做的是根据休假类型、休假次数和休假分配来检查可用的休假数。似乎我的“check_leave”由于某种原因没有得到验证而没有任何错误。感谢任何帮助!

class Leave < ActiveRecord::Base
  belongs_to :staff
  validates :staff, :leave_type, :start_date, :end_date, :number_of_days, :approved_by, presence: true
  enum leave_type: {Medical: 0, Annual: 1, Urgent: 3, "Birth Leave": 4}
  validate :check_leave, if: -> {self.number_of_days.present?}

protected

  def check_leave
    if self.leave_type == 0
      if ( self.number_of_days = self.number_of_days + LeaveAllocation.last.medical_leave_counter ) > LeaveAllocation.last.medical_leave
        self.errors.add(:number_of_days, "Days exceeded the limit")
      end
    elsif self.leave_type == 1
      if ( self.number_of_days = self.number_of_days + LeaveAllocation.last.annual_leave_counter ) > LeaveAllocation.last.annual_leave
        self.errors.add(:number_of_days, "Days exceeded the limit")
      end
    end
  end
end

【问题讨论】:

  • “不工作”是什么意思?错误?结果不正确?请给出实现的输出,然后是预期的输出,显示如何在它工作时识别它。
  • 它根本不验证 check_leave。没有错误
  • 你是说validate 没有调用你的check_leave 方法吗?或者您是说check_leave 中存在逻辑问题导致验证失败?或者您是说check_leave 中存在逻辑问题,导致它在不应该通过验证的情况下通过验证?或者是否还有其他我无法猜测的问题?
  • 它调用 check_leave 但它在不应该通过验证时通过了验证。如果您能帮我检查我的条件语句并查看是否有任何错误,那就太好了。谢谢
  • 我看到 2 件事我质疑:1) self.errors.add 的使用是不合时宜的。它应该是errors.add,如果你在某个地方有冲突,那是需要认真考虑的事情。 2) self.number_of_days = self.number_of_days + LeaveAllocation.fieldname 似乎没有按照你的想法去做。每次验证时,它都会通过 leave_counter 递增 self.number_of_days。验证中不会出现这样的副作用。

标签: ruby-on-rails ruby-on-rails-4 rails-activerecord


【解决方案1】:

在我看来,您只需要在您的条件(两者)中删除 self.number_of_days 的分配。如果我了解您要查找的内容,则应该这样做:

def check_leave
  if self.leave_type == 0
    if (self.number_of_days + LeaveAllocation.last.medical_leave_counter) > LeaveAllocation.last.medical_leave
      errors.add(:number_of_days, "Days exceeded the limit")
    end
  elsif self.leave_type == 1
    if (self.number_of_days + LeaveAllocation.last.annual_leave_counter) > LeaveAllocation.last.annual_leave
      errors.add(:number_of_days, "Days exceeded the limit")
    end
  end
end

我还从errors.add 中删除了self.,因为没有理由拥有它。您可能可以在此方法中删除所有 self. 的使用,但我会留给您,以防有我不知道的冲突。

我创建了一个简短的测试程序,以使用我创建的一些代表性数据来测试条件。测试程序在这里:

test_data = [
  { leave_type: 0, number_of_days:  2, leave_counter: 2, leave_limit: 13, result: true },
  { leave_type: 0, number_of_days: 12, leave_counter: 2, leave_limit: 13, result: false },
  { leave_type: 0, number_of_days: 12, leave_counter: 2, leave_limit: 14, result: true },
  { leave_type: 1, number_of_days:  5, leave_counter: 1, leave_limit:  9, result: true },
  { leave_type: 1, number_of_days: 12, leave_counter: 2, leave_limit: 13, result: false },
  { leave_type: 1, number_of_days: 12, leave_counter: 2, leave_limit: 14, result: true },
]

def check_leave(leave_type, number_of_days, leave_counter, leave_limit)
  if leave_type == 0
    if (number_of_days + leave_counter) > leave_limit
      return false
    end
  elsif leave_type == 1
    if (number_of_days + leave_counter) > leave_limit
      return false
    end
  end

  return true
end

test_data.each_with_index do |test, i|
  puts "#{check_leave(test[:leave_type], test[:number_of_days], test[:leave_counter], test[:leave_limit]) == test[:result] ? 'Pass' : 'Fail'}: #{i}"
end

结果在这里:

Pass: 0
Pass: 1
Pass: 2
Pass: 3
Pass: 4
Pass: 5

这是 6 个特定的测试条件,它们分别为 2 个 leave_types 确认以下 3 个条件:

  • (number_of_days + leave_counter)
  • (number_of_days + leave_counter) > leave_limit(预计验证失败)
  • (number_of_days + leave_counter) == leave_limit(期望验证通过)

这表明检查正在工作。验证失败几乎可以肯定是因为测试数据不正确。此验证中使用的 4 个字段中的任何一个都可能是错误的:

  • leave_type
  • number_of_days
  • leave_counter
  • leave_limit

剩下的唯一步骤是确认应用程序测试中使用的数据,以进行据报道无效的验证。至少需要一组测试数据(4 个必填字段的值)才能继续进行。

【讨论】:

  • 谢谢,但它仍然在不应该的时候通过所有东西(除了空白)
  • 我只能盲目地编码,而不知道您正在测试什么信息以及您期望的结果。例如,对于leave_type = 0 和number_of_days = 9、medical_leave_counter = 4 和medical_leave = 23448 的输入,预期结果是验证失败。或类似的东西。这在很大程度上取决于您在数据库中拥有哪些数据,如果不知道已知输入的结果,我无法弄清楚什么可行,什么不可行。验证通过和失败都需要多个示例。
  • 如果number_of_days和medical_leave_counter之和大于medical_leave,它应该会失败并显示错误。
  • 我知道这是算法。使用您正在使用的测试数据,它不起作用。我已经用一个测试程序更新了我的答案,该程序适用于我知道要测试的所有情况。如果您没有得到结果,我需要查看我的答案中确定的 4 个字段的精确值。
【解决方案2】:

试试这个,因为 leave_type 是一个哈希,你需要提供正确的键来获取值...

改变

  if self.leave_type == 0
  ...
  elsif self.leave_type == 1
  ...
  end

到

  if self.leave_type[:Medical] == 0
  ...
  elsif self.leave_type[:Annual] == 1
  ...
  end

【讨论】:

  • 我得到 TypeError 没有将 Symbol 隐式转换为 Integer
猜你喜欢
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-01
相关资源
最近更新 更多