2010-06-24 3 views
10

Vorrei un esempio molto semplice di un programma di base minuscolo, che legge due plug-in e li registra. Questi due plugin si agganciano al programma di base allo stesso modo in modo non conflittuale.Ruby Plugin Architecture

Sono molto nuovo a metaprogrammazione in qualsiasi linguaggio di programmazione, non sono sicuro da dove iniziare.

+1

Mi spiace essere pedante, ma non sono i plug-in associati al framework Rails, non al ruby ​​stesso? –

+0

Il framework rails ha plugin, ma sto parlando di creare un sistema di plugin nel contesto di un'applicazione ruby. Quindi dì che hai una classe che legge un file di testo. Mi piacerebbe creare un sistema di plugin che ti permetta di scrivere una classe Plugin che si collega alla classe del lettore in modo che tu possa dire, un plugin UpCase o un plugin 1337 che modifichi l'output. È un esempio di base, ma dovrebbe darti un'idea. –

+5

rubino è molto più che rotaie, anche se le rotaie sono la struttura più conosciuta là fuori. dire che i plugin sono associati con le rotaie è come dire che la benzina è associata alle auto sportive. c'è un mondo di altre cose che usano la benzina, comprese le cose non automobilistiche. –

risposta

8

ho lavorato su questo problema per un po 'di tempo. Ho provato diversi modi per farlo e ho chiesto consiglio a molte persone. non sono ancora sicuro se quello che ho è 'la strada giusta', ma funziona bene ed è facile da fare.

nel mio caso, sto specificatamente guardando la configurazione e introducendo i plugin di configurazione, ma il principio è lo stesso anche se la terminologia per la mia è specifica per la configurazione.

a un livello molto semplice, ho una classe di configurazione con nulla in esso - è vuota. Ho anche un metodo di configurazione, che restituisce la classe di configurazione e consente di richiamare i metodi su di esso:

# config.rb 
class Configuration 
end 

class MySystem 
    def self.configure 
    @config ||= Configuration.new 
    yield(@config) if block_given? 
    @config 
    end 

    Dir.glob("plugins/**/*.rb").each{|f| require f} 
end 

MySystem.configure do |config| 
    config.some_method 
    config.some_value = "whatever" 
    config.test = "that thing" 
end 

puts "some value is: #{MySystem.configure.some_value}" 
puts "test #{MySystem.configure.test}" 

per ottenere il some_method e some_value sulla classe di configurazione, ho i plugin estendono l'oggetto di configurazione tramite moduli:

# plugins/myconfig.rb 
module MyConfiguration 
    attr_accessor :some_value 

    def some_method 
    puts "do stuff, here" 
    end 
end 

class Configuration 
    include MyConfiguration 
end 

e

# plugins/another.rb 
module AnotherConfiguration 
    attr_accessor :test 
end 

class Configuration 
    include AnotherConfiguration 
end 

a caricare i plugin, è necessario solo un codice per cercare i file .RB in una cartella specifica e 'bisogno' di loro . questo codice può vivere ovunque purché venga eseguito immediatamente quando viene caricato il file che lo contiene ... probabilmente lo inserirò nella definizione di classe per MySystem o qualcosa del genere per iniziare. forse spostarlo da qualche altra parte quando ha senso.

Dir.glob("plugins/**/*.rb").each{|f| require f}

corsa config.rb e si otterrà in uscita che assomiglia a questo:

do stuff, here 
some value is: whatever 
test that thing 

ci sono un sacco di opzioni per l'attuazione delle varie parti di questo, ma questo dovrebbe farti giù per la sentiero.

2

Sembra che questo progetto può aiutare: https://github.com/eadz/plugman

non ho però trovato nulla che gestirà incorporato (GEM) Dipendenze comunque. Includere i file di Ruby è semplice, ma una volta che i plug-in iniziano a richiedere altre librerie, questo semplice modello va in pezzi (o tutti i deps devono essere installati con l'applicazione, o è necessario qualche altro meccanismo per ottenere le gemme di dipendenza del plugin nel processo).