2011-08-04 31 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 errors.countを入力するたびに0に設定されているようです。

問題オブジェクトの作成を停止する必要がありますが、属性が別のモデルオブジェクトに設定されている場合に限ります。

私はvalidate_on_createメソッドでこれを記述しようと考えましたが、もう一方のオブジェクトに渡す必要があります。

私が考えた最初の解決策は、Issueモデルに追加のフィールドを挿入し、フック内で修正することです。以下のような

何か:

Issue.can_validateが発行モデル

に加えている

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 

はしかし、これはここに最善のアプローチを思えません。簡単な方法がありますか?

答えて

5

データを検証する場合は、モデルを直接パッチし、フックを使用しないでください。フックは、HTMLをページに挿入したり、コントローラの制御フローを変更したりするために使用されます。フックを使用するということは、コードがアプリケーションを通るその1つのパスに対してのみ機能することを意味します。だから、誰かが別の場所で問題を作成すると、コードは実行されません。 Redmineのは、私がしました

それの問題クラスでそのモジュールが含まれるお使いのコード

  • を持つモジュールを作成し

    1. :あなただけの2つのことを行う必要があるパッチを作成するには

      期限が将来設定されることを要求するために、問題の検証を追加するプラグインでこの正確なことを実行します。そのためpatchので、私はそれをここに含まれますかなり単純です:class_evalメソッドの内部

      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 
      

      は、あなた自身のコードを配置する場所、私はvalidate_on_createとは異なる名前を使用することをお勧めしたいです。そうしないと、そのメソッドを使いたい場合には他のコードに問題が発生する可能性があります。

      2番目の部分(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の場合、init.rbのコードをEric Davisの応答で置き換えてください。

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