2011-08-04 27 views
3

我在编写Redmine插件时遇到了验证问题。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时error.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是除了发行模型

然而,这似乎并没有最好的方法在这里。有更容易的方法吗?

回答

5

如果你想验证数据,你应该直接修补模型,而不是使用钩子。挂钩用于将HTML插入页面或更改控制器的控制流。使用钩子也意味着你的代码只能在通过应用程序的那一个路径上工作,所以如果有人在其他地方创建了一个问题,那么你的代码将不会运行。

要建立你只需要做两件事情补丁:

  1. 创建具有您的代码模块
  2. 请管理平台包括在它的发行类

我有这个模块在插件中做了这个确切的事情,该插件添加了对问题的验证,以要求在将来设置到期日期。该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

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