Redmine hook 的验证问题

发布于 2024-11-28 03:16:46 字数 803 浏览 2 评论 0原文

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

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

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

出于测试目的,我编写了一个覆盖问题的补丁。 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 是问题模型的补充

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

I am having a validation problem when writing a Redmine plugin.

I'm writing a hook for the issue model, and as a part of the hook method, i would like to invalidate the creation of the issue, by adding a custom error:

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

For testing purposes, I have written a patch that overwrites Issue.validate_on_create, but it seems that every time when entering validate_on_create errors.count is set to zero.

I need to stop the creation of the issue object , but only when an attribute is set into another model object.

I thought about writing this in the validate_on_create method, but then I would need to pass it the other object.

The first solution that I thought about would be to insert an additional field in the Issue model, and modify it inside the hook.

Something like :

  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   

where Issue.can_validate is an addition to the Issue model

However, this does not seem the best approach here. Is there an easier way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一抹微笑 2024-12-05 03:16:46

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

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

  1. 创建一个包含您的代码的模块
  2. 让 Redmine 将该模块包含在它的 Issue 类中

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

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

您需要将其包装在调度程序中以保持开发模式下的工作。我已经在我的博客< /a>.

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

If you are wanting to validate data you should patch the models directly and not use hooks. Hooks are meant to be used to insert HTML onto a page or change the control flow of a controller. Using hooks also means that your code will only work for that one path through the application, so if someone creates an issue somewhere else then you code will not run.

To create a patch you just need to do two things:

  1. Create a module that has your code
  2. Make Redmine include that module in it's Issue class

I've done this exact thing in a plugin that adds a validation on an Issue to require that due dates are set in the future. The patch for it is rather simple so I'll include it here:

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

Inside of the class_eval is where you would put your own code, I'd recommend using a different name than validate_on_create. Otherwise you might have problems with other code if they want to use that method too.

The second part (including the module into Redmine) is rather easy. Just require the Issue class and use include to add it to the class.

# 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

You need to wrap this in the Dispatcher to keep things working in development mode. I've written about it on my blog.

Feel free to copy my plugin from github to make your changes, it's pretty simple. https://github.com/edavis10/redmine_require_issue_due_date_in_future

苹果你个爱泡泡 2024-12-05 03:16:46

从 Redmine 2.0 开始,您应该将 init.rb 中的代码替换为 Eric Davis 回复中的代码:

#init.rb
ActionDispatch::Callbacks.to_prepare do 
  require_dependency 'issue'
  Issue.send(:include, RedmineRequireIssueDueDateInFuture::Patches::IssuePatch)
end

Since Redmine 2.0, you should replace the code in init.rb by this in Eric Davis response :

#init.rb
ActionDispatch::Callbacks.to_prepare do 
  require_dependency 'issue'
  Issue.send(:include, RedmineRequireIssueDueDateInFuture::Patches::IssuePatch)
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文