2011-08-04 26 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