Redmine钩子的验证问题

时间:2011-08-04 09:47:17

标签: ruby-on-rails ruby ruby-on-rails-3 redmine redmine-plugins

编写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是问题模型的补充

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

2 个答案:

答案 0 :(得分:5)

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

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

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

    我在插件中做了这个确切的事情,在一个问题上添加了一个验证,要求在将来设置截止日期。它的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