2012-03-19 18 views
43

TL; DRrbenv: Sopravvivere senza gemsets

  • Non perdete tempo con gemsets; possono essere installate più versioni di una gemma contemporaneamente.
  • Se necessario, specificare la versione da eseguire utilizzando la notazione $ gem-based-binary _version_ args.
  • Utilizzare bundle exec quando si ha un Gemfile che specifica la versione.
gem install rails -v 3.2.13 
rails _3.2.13_ new Project2 
cd Project2 
bundle exec rails server 

UPDATE: 2015-06-04

ho scritto questa domanda tre anni fa. In parte, si basava su una falsa ipotesi, e in parte la situazione è cambiata da allora. Con l'apprezzamento di @indirect per la sua risposta originale, voglio richiamare l'attenzione sulla nuova risposta di @ kelvin (meno svalutata), riassunta sopra.

La mia falsa ipotesi: solo una singola versione di una gemma potrebbe essere installata alla volta, da qui la necessità di gemsets per isolare lo spazio dei nomi. Non vero. Più versioni di una gemma possono essere installate contemporaneamente. Il più recente verrà utilizzato quando invocato da una riga di comando, a meno che non si disponga di un Gemfile che specifica i vincoli di versione e invochi il comando tramite bundle exec o specifichi la versione come primo argomento.

Vedere anche How can I call an older version of a gem from the commandline? re: la notazione della versione di sottolineatura.


domanda originale:

ho più progetti in corso con diverse versioni di Rails. Dispongo di un flusso di lavoro (descritto di seguito) per la creazione di progetti utilizzando versioni specifiche di binari e mantenendo i progetti isolati gli uni dagli altri. Mi piacerebbe sperimentare con altri flussi di lavoro, in particolare, utilizzando rbenv anziché RVM, ma non è chiaro come farlo.

DOMANDA: Qual è la migliore pratica corrente per la creazione di più progetti rotaie, ognuno dei quali utilizza una versione diversa di rotaie, quando fanno uso di rbenv e bundler, al contrario di rbenv-GemSET o rvm ?

USE CASE: Ho due progetti di binari, denominati ProjectA e ProjectB. ProjectA è sviluppato utilizzando una versione di rails ("RailsA"), mentre ProjectB utilizza una versione diversa ("RailsB"). Come faccio a gestire l'installazione di entrambe le versioni?

IL GEMSETS APPROCCIO: Quando ho iniziato con lo sviluppo Rails, ho usato RVM. Oltre a supportare più installazioni simultanee di ruby, RVM supporta più Named Gem Sets.Ogni progetto ha una propria collezione indipendente di gemme (tra cui le rotaie si) chiamato un GemSET:

rvm gemset create RailsA 
rvm gemset use RailsA 
# RailsA. Note: My question is not version-specific. 
gem install rails --version 3.0 
rails new ProjectA 
cd ProjectA 
rvm --rvmrc use `rvm current` 
vi Gemfile 
bundle install 
cd .. 
## Now do the same for ProjectB 
rvm gemset create RailsB 
rvm gemset use RailsB 
gem install rails --version 3.2 
rails new ProjectB 
cd ProjectB 
rvm --rvmrc use `rvm current` 
vi Gemfile 
bundle install 

Nota: La stessa creazione delle cartelle di progetto dovrebbe essere fatto (secondo me) da un comando rails new utilizzando il desiderato versione di rotaie, poiché i file dello scheletro cambiano da versione a versione. (Forse dovrei rivedere questa premessa?)

L'APPROCCIO FARDELLATRICE: Ho giocato con l'utilizzo di rbenv al posto di RVM, ma non capisco il flusso di lavoro nel modo più chiaro. Nel documento README.md, Sam Stephenson scrive che "rbenv non ... gestisce i set di pietre. Bundler è un modo migliore per gestire le dipendenze delle applicazioni". C'è un plugin (rbenv-gemset) per ottenere gli stessi risultati dei set di gemme di rvm, ma Sam preferisce chiaramente usare invece Bundler. Sfortunatamente, non approfondisce l'aspetto del flusso di lavoro. Anche il sito web Bundler non collega esplicitamente tutti i punti su come isolare un progetto da un altro. Diversi blogsandgists venire in soccorso, suggerendo la ~/.bundle/config seguente file:

--- 
BUNDLE_PATH: vendor/bundle 

(BTW, non sono sicuro di ciò che il "---" è circa la documentazione non fanno menzione di esso e doesn. sembra fare la differenza)

Questo effettivamente dà ad ogni progetto di binari il proprio insieme di gemme, memorizzando le gemme in ProjectX/vendor/bundle /. Infatti, i binari stessi verranno (ri) installati lì, rendendo il progetto completamente indipendente dal resto del mio ambiente, una volta eseguito il bundle install.

Ma la elefante nella stanza è il problema di pollo e uova di creare la cartella di progetto rotaie in primo luogo !! Per creare la cartella ProjectA utilizzando RailsA, ho bisogno di installare le rotaie (e le sue numerose dipendenze) prima. Ma quando voglio creare ProjectB, devo quindi passare a utilizzare RailsB. Senza set di pietre, devo fare qualche serio aggiornamento/downgrade. Non fantastico

Una possibile soluzione è semplicemente non preoccuparsi di quale versione di rotaie utilizzo per creare la cartella ProjectX. Se poi utilizzo le guide 3.0 per creare un progetto 3.2, potrei semplicemente creare manualmente l'albero app/cespiti. Ma questo mi irrita. Non c'è un modo migliore?

+2

Suona come si vuole veramente utilizzare RVM e gemsets. Qualunque ragione particolare tu stia scegliendo NON per usare lo strumento che risolve il tuo problema in modo più elegante? –

+4

Non sono impegnato in alcun particolare strumento (e non voglio assolutamente entrare in una discussione "RVM vs rbenv"). Sono più familiare con RVM e capisco un flusso di lavoro per l'utilizzo. Mi piacerebbe capire il flusso di lavoro equivalente per rbenv, se non altro per avere fluidità con una varietà di strumenti. –

+1

Si dice che il sito web di Bundler non spiega come "isolare un progetto da un altro". Se "isolare" significa che ogni progetto ha una copia separata della stessa gemma e della stessa versione (ad es. Rack-1.4.0), Bundler non lo fa. Mantiene una singola copia di ogni gemma su disco - e qualsiasi app che ha bisogno di quella gemma e versione può usarla senza interferire con altre app.È come eseguire 2 istanze di 'bash'; non hai più copie di 'bash' su disco, ma più copie in memoria. I gemmets ti consentono di avere più copie su disco (che potrebbe essere più facile da eliminare quando non sono più necessarie) – Kelvin

risposta

12

Supponiamo di avere rotaie 3.1.0 installato, ma si desidera creare un nuovo progetto utilizzando rotaie 3.2.13 che non è installato.

Diciamo che si desidera che il nuovo progetto di essere in ~/projects/Project2.

gem install rails -v 3.2.13 
cd ~/projects 
rails _3.2.13_ new Project2 

Questo creerà la Gemfile per voi, bloccato alla versione di rotaie specificato nella riga di comando.

Ho deliberatamente omesso l'idea di conservare una copia separata di gemme per il nuovo progetto, perché ciò va contro la filosofia di Bundler, che è quella di avere tutte le gemme installate in un posto. Quando esegui i binari, Bundler sceglierà automaticamente le versioni gem corrette da quella posizione centrale. Ciò significa che un progetto può condividere gemme invece di installarne una nuova copia. (Nota, tuttavia, ciascuna versione di ruby ​​installata avrà le sue gemme. Questa è una buona cosa perché le estensioni native probabilmente non funzioneranno con le versioni ruby.)

Devi essere un po 'più consapevole, perché la maggior parte dei comandi, come rake, caricherà la versione più recente di rake installata. Avrai bisogno di eseguire bundle exec rake ... per assicurarti che sia stata caricata la versione corretta. Di solito eseguo bundle exec per tutti i comandi tranne rails. È possibile creare un alias per renderlo più breve (io uso bex). Per automatizzare questo con eseguibili gemma, è possibile utilizzare rbenv-binstubs, ma si devono ancora essere consapevoli del fatto che l'esecuzione di eseguibili non-gioiello come ruby e irb non userà automaticamente il Gemfile.

Sidenote: rails new verrà eseguito bundle install, che controllerà la versione più recente delle dipendenze. Se si desidera bundler per cercare di utilizzare gemme attualmente installati che soddisfano i requisiti di dipendenza, si può saltare il bundle install con rails new --skip-bundle, quindi eseguire bundle check nella directory app.

Sidenote 2: si supponga di voler utilizzare una versione di rubino per Project2 (ad esempio 2.1.8) diversa da quella predefinita (ad esempio 2.3.0). In tal caso, l'esecuzione gem install come sopra specificato installerà le gemme sotto 2.3.0, che è una perdita di tempo, perché avrete bisogno di installare le gemme di nuovo sotto 2.1.8. Per risolvere questo problema, è possibile forzare i comandi per utilizzare la versione preferita tramite variabile d'ambiente:

RBENV_VERSION=2.1.8 gem install rails -v 3.2.13 
cd ~/projects 
RBENV_VERSION=2.1.8 rails _3.2.13_ new Project2 
echo 2.1.8 > Project2/.ruby-version 

È potrebbe uso rbenv shell per impostare la variabile, ma mi raccomando solo che se non si vuole rbenv a auto-switch basato su file .ruby-version per la durata di tale shell. È molto facile dimenticare che hai il set di variabili, e quando fai il cd su un progetto diverso, non userà la versione che ti aspetti.

+0

re: Sidenote 2 : Penso che sarei capace di dimenticare il nome della variabile e devo cercarlo. Non vale il tempo. Meglio aprire una nuova finestra solo per una rapida sessione 'rbenv shell', chiudendo subito dopo. Personalmente, per me sarebbe più facile da ricordare. YMMV. Inoltre, se usi 'bundle exec' per i comandi _all_, _including_' rails', Bundler ti catturerà se hai dimenticato di aver eseguito 'rbenv shell' e se ne è andato in un'altra cartella di progetto. –

+0

Qual è la tua motivazione per non avviare Rails con Bundler. (re: "Solitamente eseguirò bundle exec per tutti i comandi tranne i binari") –

+0

n.b. alcuni alias sono dipendente da: alias be = 'bundle exec'; alias brs = 'be rails server'; alias brc = 'be rails console'; –

42

La maggior parte delle persone risolve questo problema installando prima la gemma delle rotaie tramite gem install rails. Se rifiuti di farlo per qualche motivo, puoi disattivare il raggruppamento automatico che Rails tenta di fare per te. Questo funzionerà completamente indipendentemente dal tuo sistema di gestione del rubino.

mkdir myapp 
cd myapp 
echo "source :rubygems" > Gemfile 
echo "gem 'rails', '3.2.2'" >> Gemfile 
bundle install --path vendor/bundle 
bundle exec rails new . --skip-bundle 

Quando richiesto, digitare "y" per sostituire il vostro Gemfile con le guide di default (o meno, come si preferisce). Poi, una volta che si è fatto:

bundle install 

Il gioco è fatto, e si hanno boostrapped una nuova applicazione Rails con la versione di vostra scelta senza installare la gemma rotaie in RubyGems.

+3

Non correlato a questa soluzione, ma non modificare mai il file .bundle/config. Se vuoi isolare le gemme per un progetto, usa 'bundle install --path vendor/bundle'. – indirect

+0

Grazie, indiretto! Potresti per favore approfondire il tuo commento? Cosa c'è di sbagliato nell'approccio ~/.bundle/config? Perché è meglio usare --path? –

+0

E mentre siamo in tema di ~/.bundle/config, cosa fa il triple-dash? –

8

C'è un buon post recente su esattamente l'argomento di gemsets/bundler qui http://rakeroutes.com/blog/how-to-use-bundler-instead-of-rvm-gemsets/ Un buon background che puoi applicare alla tua configurazione di rbenv.

+0

Ottima recensione. Se l'avessi saputo, non avrei dovuto pubblicare [il mio] (http://www.relativkreativ.at/articles/managing-multiple-rails-versions-with-rbenv) :-) –

Problemi correlati