web-dev-qa-db-ja.com

モンキーパッチのデバイス(または任意のRails gem)

Railsプロジェクトで Devise 認証gemを使用しており、フラッシュアラートで使用しているキーを変更したい(Deviseは:noticeと:alertを使用)フラッシュキーですが、:successと:errorに変更して、 Bootstrap 。)で素敵な緑/赤のボックスを表示できるようにします。

だから私はどういうわけか DeviseControllerset_flash_messageメソッドをオーバーライドできるようにしたいのです。

新しい方法は次のとおりです。

def set_flash_message(key, kind, options = {})

  if key == 'alert'
    key = 'error'
  elsif key == 'notice'
    key = 'success'
  end

  message = find_message(kind, options)
  flash[key] = message if message.present?

end

しかし、私はそれをどこに置くべきかわかりません。


更新:

回答に基づいて、次のコードを使用してconfig/initializers /overrides.rbファイルを作成しました。

class DeviseController
    def set_flash_message(key, kind, options = {})
       if key == 'alert'
          key = 'error'
       elsif key == 'notice'
          key = 'success'
       end
       message = find_message(kind, options)
       flash[key] = message if message.present?
    end
end

ただし、これにより、すべてのDeviseアクションでエラーが発生します。

ルーティングエラー:Devise :: SessionsController:Classの未定義のメソッド 'prepend_before_filter'

21
Yarin

クラスを再度開こうとすると、新しいクラスを宣言するのと同じ構文になります。

class DeviseController
end

このコードが実際のクラス宣言の前に実行された場合、Deviseによって宣言されたクラスを拡張する代わりに、Objectから継承します。代わりに私は以下を使用しようとします

DeviseController.class_eval do
  # Your new methods here
end

このように、DeviseControllerが宣言されていない場合はエラーが発生します。結果として、あなたはおそらく

require 'devise/app/controllers/devise_controller'

DeviseController.class_eval do
  # Your new methods here
end
57
aceofspades

Rails 4 @ aceofspadesの回答を使用してもうまくいきませんでした。

私はrequireを取得し続けました ':cannot load such file -- devise/app/controllers/devise_controller (LoadError)

イニシャライザのロード順序をいじくり回す代わりに、requireステートメントなしでto_prepareイベントフックを使用しました。これにより、最初のリクエストの前にモンキーパッチが確実に適用されます。この効果はafter_initializeフックに似ていますが、リロード後に開発モードでモンキーパッチが再適用されるようにします(本番モードでは結果は同じです)。

Rails.application.config.to_prepare do
  DeviseController.class_eval do
    # Your new methods here
  end
end

N.B. Rails to_prepareに関するドキュメントはまだ正しくありません:これを参照してください Githubの問題

14
ARO

次のように、フラッシュハッシュの属性のオーバーライド初期化子とエイリアスを追加するのはどうですか?

class ActionDispatch::Flash::FlashHash
  alias_attribute :success, :notice
  alias_attribute :error, :alert
end

これにより、アプリケーションがflash [:notice]またはflash [:success](flash.noticeおよびflash.success)を読み取ることができるようになります。

3
Laura Popa

イニシャライザファイル内:

module DeviseControllerFlashMessage
  # This method is called when this mixin is included
  def self.included klass
    # klass here is our DeviseController

    klass.class_eval do
      remove_method :set_flash_message
    end
  end

  protected 
  def set_flash_message(key, kind, options = {})
    if key == 'alert'
      key = 'error'
    elsif key == 'notice'
      key = 'success'
    end
    message = find_message(kind, options)
    flash[key] = message if message.present?
  end
end

DeviseController.send(:include, DeviseControllerFlashMessage)

これはかなり残酷ですが、あなたが望むことをします。ミックスインは前のset_flash_messageメソッドを削除し、サブクラスを強制的にミックスインメソッドにフォールバックします。

編集:ミックスインがクラスに含まれている場合、self.includedが呼び出されます。 klassパラメーターは、ミックスインが含まれているクラスです。この場合、klassはDeviseControllerであり、remove_methodを呼び出します。

3
RedXVII

初期化子で、スーパークラスを維持しながらDeviseControllerを上書きする必要があります。

何かのようなもの:

class DeviseController < Devise.parent_controller.constantize
    def set_flash_message(key, kind, options = {})
       if key == 'alert'
           key = 'error'
       elsif key == 'notice'
           key = 'success'
       end
       message = find_message(kind, options)
       flash[key] = message if message.present?
    end
end
1
Borski

私はこれが古いスレッドであることを知っていますが、これはまだ役立つかもしれません。エンジンcalled_fromパスを使用して、gemディレクトリからファイルを要求できるはずです。

 require File.expand_path( '../../ app/helpers/devise_helper'、Devise :: Engine.called_from)
 require File.expand_path( '../../ app/controllers/Devise_controller '、Devise :: Engine.called_from)
 
 DeviseController.class_eval do 
#ここに新しいメソッド
 end 
0
userbard

これは、initialize Railsフォルダーに配置する必要がある種類のものです。これは、特にこのアプリケーションのカスタム構成であるため、次に次のように使用する必要があります。

class DeviseController
    def set_flash_message(key, kind, options = {})
       if key == 'alert'
          key = 'error'
       elsif key == 'notice'
          key = 'success'
       end
       message = find_message(kind, options)
       flash[key] = message if message.present?
    end
end

次に、期待される動作を取得する必要があります。私はテストしていないので、それが役立つことを願っています、plsはフィードバックを与えません、そして私はあなたが異なる何かを試すのを手伝います。

0
vinicius gati