编写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方法中写这个,但是我需要把它传递给另一个对象。
我想到的第一个解决方案是在Issue模型中插入一个额外的字段,并在钩子内修改它。
类似的东西:
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是问题模型的补充
但是,这似乎不是最好的方法。有更简单的方法吗?
答案 0 :(得分:5)
如果您想要验证数据,您应该直接修补模型而不是使用钩子。钩子用于将HTML插入页面或更改控制器的控制流。使用钩子也意味着你的代码只适用于通过应用程序的那条路径,所以如果有人在其他地方创建了一个问题,那么你的代码将无法运行。
要创建补丁,您只需要做两件事:
我在插件中做了这个确切的事情,在一个问题上添加了一个验证,要求在将来设置截止日期。它的patch非常简单,所以我将其包含在这里:
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中以使开发模式下的工作正常。我在my blog上写过这篇文章。
随意从github复制我的插件进行更改,这很简单。 https://github.com/edavis10/redmine_require_issue_due_date_in_future
答案 1 :(得分: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