Что такое пакетные грабли exec?

351

Что bundle exec rake db:migrateзначит? Или просто bundle exec rake <command>в общем?

Я понимаю, что bundleзаботится о сохранении вещей в Gemfile. Я знаю, что означает слово «exec». Я понимаю, что это rakeподдерживает все разные вещи, которые вы можете сделать, и я знаю, что db:migrateэто одна из них. Я просто не знаю, что все эти слова делают вместе. Почему следует bundleиспользовать для выполнения rakeмиграции базы данных?

JnBrymn
источник

Ответы:

468

bundle execявляется командой Bundler для выполнения скрипта в контексте текущего комплекта (тот из Gemfile вашего каталога ). rake db:migrateэто скрипт, где db - это пространство имен, а migrate - это определенное имя задачи.

Таким образом, bundle exec rake db:migrateвыполняется скрипт rake с командой db:migrateв контексте текущего пакета.

Что касается "почему?" Я процитирую со страницы упаковщика :

В некоторых случаях запуск исполняемых файлов без них bundle execможет сработать, если исполняемый файл установлен в вашей системе и не содержит каких-либо драгоценных камней, конфликтующих с вашим комплектом.

Однако это ненадежно и является источником значительной боли. Даже если это выглядит так, как будто оно работает, оно может не сработать в будущем или на другом компьютере.

ghoppe
источник
7
Означает ли это, что мы всегда должны запускать bundle exec, я использовал менеджер версий ruby ​​для установки ruby ​​и ruby ​​на рельсы.
Прадип Шарма
11
@ Edmund «Связка» - это английское слово, означающее группу похожих вещей, обычно аккуратно связанных. Конкретно в этом вопросе он относится к группе Gems (автономных библиотек кода ruby). Bundler - это название программного обеспечения, которое мы используем здесь для управления Gems. И bundleэто команда, которая используется Bundler.
ghoppe
2
У меня сложилось впечатление, что всякий раз, когда мы переходим к папке с Gemfile, оболочка будет автоматически использовать версии, указанные в Gemfile (например, версия Ruby). Исходя из этого предположения, я подумал, что rake db: migrate всегда будет работать без пакета exec. CMIIW
Пахлеви Фикри Аулия
1
@PahleviFikriAuliya, это верно, только если у вас есть .ruby-gemsetфайл в корне вашего проекта. Существует также .ruby-versionфайл, который устанавливает вашу версию ruby ​​при использовании RVM.
сом
1
На связанной странице больше не упоминается указанная вами цитата. Пожалуйста, исправьте, спасибо.
Гауранг Тандон
153

Вы работаете bundle execв программе. Создатели программы написали это, когда были доступны определенные версии драгоценных камней. Программа Gemfile указывает версии драгоценных камней, которые решили использовать создатели. То есть скрипт был создан для правильной работы с этими версиями гемов.

Ваш общесистемный Gemfile может отличаться от этого Gemfile. У вас могут быть новые или более старые драгоценные камни, с которыми этот сценарий не играет хорошо. Эта разница в версиях может привести к странным ошибкам.

bundle execпоможет вам избежать этих ошибок. Он выполняет скрипт, используя гемы, указанные в Gemfile скрипта, а не общесистемный Gemfile. Он выполняет определенные версии драгоценных камней с магией псевдонимов оболочки.

Смотрите больше на странице man .

Вот пример Gemfile:

source 'http://rubygems.org'

gem 'rails', '2.8.3'

Здесь bundle execбудет выполняться скрипт с использованием rails версии 2.8.3, а не какой-либо другой версии, которую вы, возможно, установили для всей системы.

Роза Перроне
источник
9
Мне нравится этот ответ лучше, чем выбранный ОП: D! Гораздо понятнее.
mauricioschneider
1
Итак, добавим к этому примеру: если человек просто выбежал, rake db:migrateуходя, bundle execто он выполнялся бы с использованием общесистемного Gemfile, где у него может быть стойка на 1.5.2 (самое позднее)?
Smokin Joe
гораздо лучший ответ, с конкретными примерами.
Анбизкад
2
Поэтому bundle execиспользует «специфичные для приложения» локальные гемы в вашем Gemfile вашего приложения и bundleиспользует «специфичные для машины» глобальные гемы, если вы это сделали gem install a_certain_gem. местный против глобального
анбизкад
Намного лучший ответ, чем выбранный.
Благо,
9

Это часто встречается, когда на вашем компьютере установлены различные версии gemfile.lock. Вы можете получить предупреждение после запуска рейка (или rspec или других), таких как:

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.

Предшествующий bundle execговорит бандеру выполнить эту команду независимо от разницы версий. Не всегда есть проблема, однако, вы можете столкнуться с проблемами.

К счастью, есть жемчужина, которая решает это: rubygems-bundler.

$ gem install rubygems-bundler

$ $ gem regenerate_binstubs

Тогда попробуйте снова свои грабли, rspec или что-то еще.

Бенджамин Данфи
источник
Все еще отличное решение в 2020 году.
Brateq
6

Вероятно, следует упомянуть, что есть способы пропустить bundle exec(все они изложены в главе 3.6.1 учебника Майкла Хартла по Ruby on Rails ).

Самое простое - просто использовать достаточно актуальную версию RVM (> = 1.11.x).

Если вы ограничены более ранней версией RVM, вы всегда можете использовать этот метод, также упомянутый calasyr :

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

bundler_stubsКаталог также должен затем быть добавлены к.gitignore файл.

Третий вариант - использовать rubygems-bundlerгем, если вы не используете RVM:

$ gem install rubygems-bundler
$ gem regenerate_binstubs
tschale
источник
1

Когда вы напрямую запускаете задачу rake или запускаете какой-либо двоичный файл гема, нет гарантии, что команда будет работать так, как ожидается. Может случиться так, что в вашей системе уже установлен тот же самый гем с версией 1.0, но в вашем проекте более поздняя версия 2.0. В этом случае вы не можете предсказать, какой из них будет использоваться.

Для обеспечения желаемой версии гема вы используете bundle execкоманду, которая будет выполнять двоичный файл в контексте текущего пакета. Это означает, что когда вы используете bundle exec, bundler проверяет версию gem, настроенную для текущего проекта, и использует ее для выполнения задачи.

Я также написал пост об этом, который также показывает, как мы можем избежать его использования с помощью заглушек bin.

Аджит Сингх
источник
1

Я не использовал bundle execмного, но сейчас настраиваю.

У меня были случаи, когда использовались неправильные грабли, и я тратил много времени на поиск проблемы. Это поможет вам избежать этого.

Вот как настроить RVM, чтобы вы могли использовать bundle execпо умолчанию в определенном каталоге проекта:

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

calasyr
источник
0

Это означает использование rake, о котором осведомлен упаковщик, и который является частью вашего Gemfile, поверх любых граблей, о которых не знает упаковщик, и запустите задачу db: migrate.

Омар Куреши
источник