25

Ho trovato alcuni articoli che affrontano il problema degli helper all'interno di un motore non accessibili all'applicazione (padre) che consuma. Per essere sicuri che siamo tutti sulla stessa pagina, diciamo che abbiamo questo:Rails 3.1: modo migliore per esporre l'helper di un motore nell'app client

module MyEngine 
    module ImportantHelper 
    def some_important_helper 
     ...do something important... 
    end 
    end 
end 

Se si guarda la documentazione rails engine in "aiutanti isolata del motore" del (L293), che dice:

# Sometimes you may want to isolate engine, but use helpers that are defined for it. 
    # If you want to share just a few specific helpers you can add them to application's 
    # helpers in ApplicationController: 
    # 
    # class ApplicationController < ActionController::Base 
    # helper MyEngine::SharedEngineHelper 
    # end 
    # 
    # If you want to include all of the engine's helpers, you can use #helpers method on an engine's 
    # instance: 
    # 
    # class ApplicationController < ActionController::Base 
    # helper MyEngine::Engine.helpers 
    # end 

quindi, se io chiedo a nessuno di consumare il mio motore di aggiungere questo alla loro application_controller.rb, poi si otterrà l'accesso a tutti i miei metodi di supporto importanti:

class ApplicationController < ActionController::Base 
    helper MyEngine::ImportantHelper 
end 

questo è quello che voglio e ho funziona, ma è una specie di sofferenza, soprattutto se, come è il mio caso d'uso, tutto ciò che il motore espone può/deve essere usato ovunque nell'app che consuma. Così ho scavato in giro un po 'più e ha trovato una soluzione che mi ha suggerito di effettuare le seguenti operazioni:

module MyEngine 
    class Engine < Rails::Engine 
    isolate_namespace MyEngine 

    config.to_prepare do 
     ApplicationController.helper(ImportantHelper) 
    end 
    end 
end 

Ora, questo è esattamente quello che voglio: per aggiungere tutto il mio metodo ImportantHelper al aiutante applicazione dell'app genitore. Tuttavia, non funziona. Qualcuno può aiutarmi a capire perché questa soluzione migliore non funziona?

Sto correndo rubino 1.8.7 con rotaie 3.1.3. Fammi sapere se mi sono perso qualche informazione importante pertinente al problema, e grazie in anticipo.

risposta

44

È possibile creare un inizializzatore per raggiungere questo obiettivo in questo modo:

module MyEngine 
    class Engine < Rails::Engine 
    initializer 'my_engine.action_controller' do |app| 
     ActiveSupport.on_load :action_controller do 
     helper MyEngine::ImportantHelper 
     end 
    end 
    end 
end 
+0

In realtà puoi semplificare ancora di più: helper MyEngine :: ImportantHelper con fuori l'invio. Ho aggiornato il mio post. – JDutil

+0

È cambiato? Sembra che * tutti * i miei aiutanti vengano caricati automaticamente senza il codice sopra! Ecco il mio motore: https: // github.com/sientia-jmu/iq_menu –

+0

Sembra davvero che tutti gli helper siano inclusi automaticamente in ogni controller, almeno quando si ha un motore '--full'. –

1
module YourEngine 
    module Helpers 
    def a_helper 
    end 

    ... 
    end 
end 

ActionController::Base.send(:helper, YourEngine::Helpers) 
6

Se si desidera mantenere il codice nel motore, invece di ogni applicazione attuazione, utilizzare questo:

module MyEngine 
    class Engine < Rails::Engine 
    isolate_namespace MyEngine 

    config.to_prepare do 
     MyEngine::ApplicationController.helper Rails.application.helpers 
    end 

    end 
end 
1

Includere questo codice in engine.rb è anche essere molto utile

config.before_initialize do 
    ActiveSupport.on_load :action_controller do 
    helper MyEngine::Engine.helpers 
    end 
end 

Fondamentalmente il tuo motore sembrerebbe

module MyEngine 
    class Engine < Rails::Engine 
    isolate_namespace MyEngine 

    # Here comes the code quoted above 

    end 
end