【问题标题】:Validation problem with a Redmine hookRedmine 挂钩的验证问题
【发布时间】:2011-08-04 09:47:16
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    我已经在一个插件中完成了这件事,该插件添加了对问题的验证,以要求在未来设置到期日期。 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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-10
        • 1970-01-01
        • 2023-03-13
        相关资源
        最近更新 更多