O que significa bundle exec rake?

351

O que bundle exec rake db:migratesignifica isso ? Ou apenasbundle exec rake <command> em geral?

Entendo que bundlecuida de manter as coisas no Gemfile. Eu sei o que a palavra "exec" significa. Entendo que rakemantém todas as diferentes coisas de script que você pode fazer e sei que db:migrateé uma delas. Só não sei o que todas essas palavras estão fazendo juntas. Por que deve bundleser usado rakepara executar uma migração de banco de dados?

JnBrymn
fonte

Respostas:

468

bundle execé um comando do Bundler para executar um script no contexto do pacote atual (o do Gemfile do seu diretório ). rake db:migrateé o script em que db é o espaço para nome e migrate é o nome da tarefa definido.

Portanto, bundle exec rake db:migrateexecuta o script rake com o comando db:migrateno contexto do pacote atual.

Quanto ao "por quê?" Vou citar a partir da página do empacotador :

Em alguns casos, executar executáveis ​​sem bundle exec pode funcionar, se o executável estiver instalado no seu sistema e não atrair gemas que entrem em conflito com o seu pacote.

No entanto, isso não é confiável e é a fonte de uma dor considerável. Mesmo que pareça funcionar, pode não funcionar no futuro ou em outra máquina.

ghoppe
fonte
7
Isso significa que devemos sempre executar o bundle exec; usei o ruby ​​version manager para instalar o ruby ​​e o ruby ​​nos trilhos.
Pradeep Sharma
11
@ Edmund Um "pacote" é uma palavra em inglês, que significa um grupo de coisas semelhantes, geralmente amarradas ordenadamente. Especificamente nesta pergunta, refere-se a um grupo de Gems (bibliotecas de códigos ruby ​​independentes). Bundler é o nome do software que estamos usando aqui para gerenciar o Gems. E bundleé o comando usado pelo Bundler.
ghoppe
2
Tenho a impressão de que sempre que fizermos o cd para uma pasta com Gemfile, o shell usará automaticamente as versões especificadas no Gemfile (por exemplo, versão Ruby). Com base nessa suposição, pensei que o rake db: migrate sempre funcionaria bem sem o bundle exec. CMIIW
Pahlevi Fikri Auliya
11
@PahleviFikriAuliya que só é verdadeiro se você tiver um .ruby-gemsetarquivo na raiz do projeto. Há também um .ruby-versionarquivo que define sua versão ruby ​​se estiver usando o RVM.
Catfish
11
A página vinculada não menciona mais a cotação que você especificou. Por favor, corrija, obrigado.
Gaurang Tandon
153

Você está executando bundle execum programa. Os criadores do programa o escreveram quando certas versões de gemas estavam disponíveis. O programa Gemfile especifica as versões das gemas que os criadores decidiram usar. Ou seja, o script foi feito para ser executado corretamente nessas versões de gemas.

O seu Gemfile em todo o sistema pode diferir deste Gemfile. Você pode ter joias mais novas ou mais antigas, com as quais esse script não funciona bem. Essa diferença de versão pode gerar erros estranhos.

bundle execajuda a evitar esses erros. Ele executa o script usando as gemas especificadas no Gemfile do script, em vez do Gemfile em todo o sistema. Ele executa certas versões de gemas com a magia de aliases de shell.

Veja mais na página do manual .

Aqui está um exemplo do Gemfile:

source 'http://rubygems.org'

gem 'rails', '2.8.3'

Aqui, você bundle execexecutaria o script usando o rails versão 2.8.3 e não outra versão que você possa ter instalado em todo o sistema.

Rose Perrone
fonte
9
Gosto mais desta resposta do que a escolhida pelo OP: D! Muito mais claro.
mauricioschneider
11
Então, para adicionar a este exemplo: se a pessoa simplesmente rake db:migratesaiu deixando de fora bundle exec, ela seria executada usando um Gemfile em todo o sistema em que alguém pode ter um rack em 1.5.2 (mais recente)?
Smokin Joe
resposta muito melhor, com exemplos concretos.
ahnbizcad
2
Portanto, bundle execuse as gemas locais "específicas do aplicativo" no seu Gemfile do seu aplicativo e bundleuse as gemas globais "específicas da máquina", se você o fez gem install a_certain_gem. local vs global
ahnbizcad
Resposta muito melhor do que a escolhida.
Boon
9

Isso ocorre muito quando seu gemfile.lock possui versões diferentes das gemas instaladas em sua máquina. Você pode receber um aviso após executar o rake (ou rspec ou outros), como:

You have already activated rake 10.3.1, but your Gemfile requires rake 10.1.0. Prepending "bundle exec" to your command may solve this.

A adição antecipada bundle execinforma ao bundler para executar este comando, independentemente do diferencial de versão. Nem sempre há um problema; no entanto, você pode ter problemas.

Felizmente, existe uma jóia que resolve isso: rubygems-bundler.

$ gem install rubygems-bundler

$ $ gem regenerate_binstubs

Em seguida, tente seu rake, rspec ou qualquer outra coisa.

Benjamin Dunphy
fonte
Ainda é uma ótima solução em 2020.
Brateq 04/04
6

Provavelmente, deve-se mencionar que existem maneiras de omitir bundle exec(todas elas são indicadas no capítulo 3.6.1 do livro Tutorial de Michael Hartls Ruby on Rails ).

O mais simples é usar apenas uma versão suficientemente atualizada do RVM (> = 1.11.x).

Se você está restrito a uma versão anterior do RVM, sempre pode usar este método também mencionado por calasyr :

$ rvm get head && rvm reload
$ chmod +x $rvm_path/hooks/after_cd_bundler
$ bundle install --binstubs=./bundler_stubs

O bundler_stubsdiretório também deve ser adicionado ao .gitignorearquivo.

Uma terceira opção é usar a rubygems-bundlergema se você não estiver usando o RVM:

$ gem install rubygems-bundler
$ gem regenerate_binstubs
tschale
fonte
1

Quando você executa diretamente a tarefa rake ou executa qualquer arquivo binário de uma gema, não há garantia de que o comando se comporte conforme o esperado. Porque pode acontecer que você já tenha a mesma gema instalada em seu sistema, com uma versão say 1.0, mas no seu projeto você tenha uma versão superior say 2.0. Nesse caso, você não pode prever qual será usado.

Para impor a versão desejada da gema, você precisa da ajuda do bundle execcomando que executaria o binário no contexto do pacote atual. Isso significa que, quando você usa o bundle exec, o bundler verifica a versão da gem configurada para o projeto atual e a usa para executar a tarefa.

Também escrevi um post sobre isso, que também mostra como podemos evitar usá-lo usando stubs de bin.

Ajit Singh
fonte
1

Não usei bundle execmuito, mas estou configurando agora.

Eu tive casos em que o rake errado foi usado e perdi muito tempo rastreando o problema. Isso ajuda a evitar isso.

Veja como configurar o RVM para que você possa usar bundle execpor padrão em um diretório de projeto específico:

https://thoughtbot.com/blog/use-bundlers-binstubs

calasyr
fonte
0

Significa usar rake de que o bundler está ciente e faz parte do seu Gemfile sobre qualquer rake de que o bundler não está ciente e executar a tarefa db: migrate.

Omar Qureshi
fonte