Rotaie estendentisi motori funzionalità
-
23-10-2019 - |
Domanda
Ho un motore che definisce alcuni modelli e controllori. Voglio essere in grado di estendere le funzionalità di alcuni modelli / controller nella mia applicazione (ad es. L'aggiunta di metodi) senza perdere la funzionalità originale del modello / controller dal motore. Ovunque ho letto che è sufficiente per definire controller con lo stesso nome nella propria applicazione e Rails li unire automaticamente, tuttavia non funziona per me e controller del motore viene semplicemente ignorato (non credo che è ancora caricato).
Soluzione 3
Proprio se qualcun altro corre nella stessa questione un po 'di tempo in futuro, questo è il codice che ho scritto che fissa il mio problema:
module ActiveSupport::Dependencies
alias_method :require_or_load_without_multiple, :require_or_load
def require_or_load(file_name, const_path = nil)
if file_name.starts_with?(RAILS_ROOT + '/app')
relative_name = file_name.gsub(RAILS_ROOT, '')
@engine_paths ||= Rails::Initializer.new(Rails.configuration).plugin_loader.engines.collect {|plugin| plugin.directory }
@engine_paths.each do |path|
engine_file = File.join(path, relative_name)
require_or_load_without_multiple(engine_file, const_path) if File.file?(engine_file)
end
end
require_or_load_without_multiple(file_name, const_path)
end
end
Ciò richiederà automaticamente i file dal motore prima di richiedere dall'applicazione se il percorso del file inizia con 'app'.
Altri suggerimenti
require MyEngine::Engine.root.join('app', 'models', 'my_engine', 'my_model')
prima della definizione della classe del modello nell'applicazione.
È possibile aggiungere queste righe a voi file di modulo del motore nella directory principale lib:
def self.root
File.expand_path(File.dirname(File.dirname(__FILE__)))
end
def self.models_dir
"#{root}/app/models"
end
def self.controllers_dir
"#{root}/app/controllers"
end
Poi si ha la possibilità nel ricorso principale (l'applicazione facendo uso del motore) per richiedere i file necessari dal motore. Questo è bello perché è mantenere Rails Motori funzionalità predefinita e hanno anche un facile strumento per fare uso di normale eredità rubino, senza la necessità di patch.
EX:
#ENGINE Model -
class User < ActiveRecord::Base
def testing_engine
puts "Engine Method"
end
end
#MAIN APP Model -
require "#{MyEngine.models_dir}/user"
class User
def testing_main_app
puts "Main App Method"
end
end
#From the Main apps console
user = User.new
puts user.testing_engine #=> "Engine Method"
puts user.tesing_main_app #=> "Main App Method"
Questo è vero. Il controller che si trova prima verrà utilizzata.
Quindi, per farlo funzionare si potrebbe avere due opzioni:
- creare una copia locale del controller, e modificare il metodo è necessario
- se si ha il controllo del plug-in, è possibile creare un modulo contenente il codice e includono il codice in entrambi i controller, solo l'override del metodo nel controller locale. Secondo me, dato che non c'è ereditarietà multipla, che è l'unico modo.
Spero che questo aiuti.
È possibile modificare l'ordine di caricamento del motore per evitare il richiedono su ciascuno dei vostri modelli.
In config / application.rb aggiungere questa riga:
module MyApp
class Application
config.railties_order = [MyEngine::Engine, :main_app, :all]
end
end
Questo farà sì che i modelli da MyEngine vengono caricati prima MyApp
Non ho mai usato Motori di prima, ma non si può definire un nuovo controller che eredita dal controller forniti dal motore