3

我在编写 Redmine 插件时遇到了验证问题。

我正在为问题模型编写一个钩子,作为钩子方法的一部分,我想通过添加一个自定义错误来使问题的创建无效:

  def controller_issues_new_before_save( context = { } )
     context[:issue].errors.add(:due_date, "A custom error")
  end

出于测试目的,我编写了一个覆盖 Issue.validate_on_create 的补丁,但似乎每次输入 validate_on_create 时,errors.count 都设置为零。

我需要停止创建问题对象,但仅在将属性设置到另一个模型对象时。

我想过在 validate_on_create 方法中写这个,但是我需要将它传递给另一个对象。

我想到的第一个解决方案是在问题模型中插入一个附加字段,并在钩子内修改它。

就像是 :

  def controller_issues_new_before_save( context = { } )
    context[:issue].can_validate = false
  end

  def validate_on_create
    unless can_validate 
      errors.add("error", "A custom error")
    end
  end   

其中 Issue.can_validate 是对问题模型的补充

但是,这似乎不是最好的方法。有没有更简单的方法?

4

2 回答 2

5

如果你想验证数据,你应该直接修补模型而不是使用钩子。挂钩旨在用于将 HTML 插入页面或更改控制器的控制流。使用钩子还意味着您的代码将仅适用于通过应用程序的那一条路径,因此如果有人在其他地方创建问题,那么您的代码将无法运行。

要创建补丁,您只需要做两件事:

  1. 创建一个包含您的代码的模块
  2. 使 Redmine 将该模块包含在其问题类中

我已经在一个插件中完成了这件事,该插件添加了对问题的验证,以要求在未来设置到期日期。它的补丁相当简单,所以我将它包含在这里:

module RedmineRequireIssueDueDateInFuture
  module Patches
    module IssuePatch
      def self.included(base)
        base.class_eval do
          unloadable

          validate :due_date_in_future

          protected
          def due_date_in_future
            return true if due_date.nil?

            if due_date.to_time < Date.today.beginning_of_day
              errors.add :due_date, :not_in_future
            end

          end

        end
      end
    end
  end
end

class_eval 内部是您放置自己代码的地方,我建议使用与 validate_on_create 不同的名称。否则,如果其他代码也想使用该方法,您可能会遇到问题。

第二部分(包括 Redmine 中的模块)相当简单。只需要 Issue 类并使用 include 将其添加到类中。

# init.rb
require 'dispatcher'
Dispatcher.to_prepare :redmine_require_issue_due_date_in_future do
  require_dependency 'issue'
  Issue.send(:include, RedmineRequireIssueDueDateInFuture::Patches::IssuePatch)
end

您需要将其包装在 Dispatcher 中以保持开发模式下的工作。我已经在我的博客上写过它。

随意从 github 复制我的插件来进行更改,这非常简单。https://github.com/edavis10/redmine_require_issue_due_date_in_future

于 2011-08-04T22:59:22.597 回答
4

从 Redmine 2.0 开始,您应该在 Eric Davis 响应中替换 init.rb 中的代码:

#init.rb
ActionDispatch::Callbacks.to_prepare do 
  require_dependency 'issue'
  Issue.send(:include, RedmineRequireIssueDueDateInFuture::Patches::IssuePatch)
end
于 2014-01-09T16:40:13.587 回答