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).

È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top