Статьи

Отделение Bundler: тщательный взгляд на утилиты Bundler

Bundler

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

Эта статья будет посвящена утилитам Bundler , которые являются командами, поставляемыми с Bundler, и не считаются основными командами. Кстати, вот все команды Bundler, разделенные на то, являются ли они первичными или служебными:

  • Основной : установка, обновление, пакет, exec, config, помощь
  • Утилиты : проверка, список, шоу, устаревшие, консоль, открытие, блокировка, а именно, init, gem, платформа, clean, binstubs, inject

Сегодня я расскажу об этой второй группе, чтобы немного больше узнать о недооцененных инструментах, которые предоставляет Bundler. Полагаю, вы узнаете хотя бы одну новость о Бандлере. Я знаю, что сделал. Если я ошибаюсь, не стесняйтесь направлять все жалобы в /dev/null .

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

комплектация init

Если вы обнаружите, что создаете одноразовые проекты Ruby и вручную пишете новый Gemfile, то вам следует использовать пакетный bundle init . Я делаю это довольно много, где я создаю Gemfile и вручную добавляю source "https://rubygems.org" и т. Д. Это кажется глупым, поскольку я могу просто напечатать:

 $ bundle init Writing new Gemfile to /path/Gemfile 

Это создает Gemfile, который выглядит следующим образом:

 # A sample Gemfile source "https://rubygems.org" # gem "rails" 

Ницца. Теперь я могу перестать беспокоиться о том, что у меня была опечатка в https:/roobygemmms.org и просто приступить к работе, добавляя свои гемы в файл.

Также, если у вас есть .gemspec который содержит зависимости для вашего драгоценного камня, вы можете указать --gemspec=<name of gem>.gemspec и сгенерированный Gemfile будет содержать драгоценные камни из упомянутого драгоценного камня. Это даже создаст группу development для ваших зависимостей разработки.

Хорошо, давайте раскомментируем эту линию gem "rails" чтобы у нас было что поиграть.

список расслоений

Хотите знать, что находится в текущем комплекте, но вам лень открывать Gemfile? Ну, тогда напечатайте bundle list и вы получите что-то вроде:

 $ bundle list Gems included by the bundle: * actioncable (5.0.0) * actionmailer (5.0.0) * actionpack (5.0.0) * actionview (5.0.0) * activejob (5.0.0) * activemodel (5.0.0) .... 

Прежде чем отклонить bundle list пакетов как тривиальный, вы должны знать, что он использует Gemfile.lock, чтобы сказать вам, что к чему. Однако, если вы удалите этот файл и bundle list вы получите:

 $ rm Gemfile.lock $ bundle list Starting resolution (2016-07-27 12:56:04 -0400) Creating possibility state for rails (1 remaining) Attempting to activate rails (5.0.0) Activated rails at rails (5.0.0) Requiring nested dependencies (activesupport (= 5.0.0), actionpack (= 5.0.0), actionview (= 5.0.0), activemodel (= 5.0.0), activerecord (= 5.0.0), actionmailer (= 5.0.0), activejob (= 5.0.0), actioncable (= 5.0.0), railties (= 5.0.0), bundler (< 2.0, >= 1.3.0), sprocket s-rails (>= 2.0.0)) Creating possibility state for sprockets-rails (>= 2.0.0) (1 remaining) Attempting to activate sprockets-rails (3.1.1) Activated sprockets-rails at sprockets-rails (3.1.1) Requiring nested dependencies (sprockets (>= 3.0.0), actionpack (>= 4.0), activesupport (>= 4.0)) Creating possibility state for activesupport (>= 4.0) (1 remai .... 

Итак, Bundler проходит фазу разрешения с нуля и создает новый Gemfile.lock. Sassy. Кстати, в последних документах Bundler ничего не говорится о bundler list пакетов, поэтому я думаю, что он может быть постепенно сокращен …

проверка пакета

Иногда, когда вы возвращаетесь в приложение для выполнения какой-либо работы, остается загадкой, была ли завершена bundle install комплекта и все ли ваши зависимости в порядке. Ну, чтобы решить эту загадку, просто наберите:

 $ bundle check The following gems are missing * rake (11.2.2) * i18n (0.7.0) * minitest (4.7.5) * multi_json (1.12.1) * thread_safe (0.3.5) * tzinfo (0.3.51) * activesupport (4.0.2) * builder (3.1.4) * erubis (2.7.0) * rack (1.5.5) * rack-test (0.6.3) * actionpack (4.0.2) * mime-types (1.25.1) * polyglot (0.3.5) * treetop (1.4.15) * mail (2.5.4) * actionmailer (4.0.2) * activemodel (4.0.2) * activerecord-deprecated_finders (1.0.4) * arel (4.0.2) * activerecord (4.0.2) * hike (1.2.3) * thor (0.19.1) * railties (4.0.2) * tilt (1.4.1) * sprockets (2.12.4) * sprockets-rails (2.0.1) * rails (4.0.2) Install missing gems with `bundle install` 

Вот и ты. Он не только сообщает нам, что зависимости не установлены, но и сообщает, какие из них отсутствуют. После bundle install мы видим:

 $ bundle check The Gemfile's dependencies are satisfied 

Здорово. Проверка выполняется путем просмотра различных gemspecs в $GEM_HOME/specifications . Таким образом, вполне возможно удалить установленный драгоценный камень из кеша драгоценного камня, но имейте bundle check говорят, что все хорошо. Конечно, вам придется сделать что-то глупое, чтобы добраться до этой точки, но вы здесь.

bundle check также создаст Gemfile.lock, если он отсутствует. Доступны следующие опции:

  • --dry-run : говорит вам, чего не хватает, но не собирает Gemfile.lock
  • --path=PATH : использует другой путь для поиска драгоценных камней. Это «запоминающийся вариант» (подробнее об этом через секунду)
  • --gemfile=FILE : использовать FILE вместо Gemfile.

Sidenote: запомненные варианты

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

 $ bundle check --path=./gems The following gems are missing * rake (11.2.2) * concurrent-ruby (1.0.2) * i18n (0.7.0) * minitest (5.9.0) ... Install missing gems with `bundle install` 

Он создает каталог ./gems и создает (или изменяет) ./.bundle/config устанавливая BUNDLE_PATH в ./gems :

 $ bundle config ...usual... bin Set for your local app (/path/.bundle/config): "./bin" path Set for your local app (/path/.bundle/config): "/path/gems" 

Кроме того, если вы cat ./.bundle/config :

 $ cat ./.bundle/config --- BUNDLE_BIN: "./bin" BUNDLE_PATH: "/Users/ggoodrich/projects/bundler/gems" BUNDLE_DISABLE_SHARED_GEMS: true 

Вы можете видеть, что локальная конфигурация изменяется в зависимости от значения, которое я использовал для --path . Это можно сбросить с помощью bundle install --system . Я буду обозначать запомненные варианты с (RO) с этого момента.

связка шоу

Как вы можете знать или не знать, Bundler (по умолчанию) установит текущий пакет в $GEM_HOME . Если, конечно, вы не скажете это сделать иначе. Если вы не уверены, где находится конкретный камень, сделайте следующее:

 $ bundle show tzinfo <YOUR $GEM_HOME>/gems/tzinfo-1.2.2 

Это может быть полезно, если вы хотите просмотреть источник для данного драгоценного камня или чего-то еще. Кроме того, если вы не предоставите имя драгоценного камня, вы получите тот же вывод, что и в bundle list . Однако, если вы добавите параметр --paths , он покажет вам пути ко ВСЕМ драгоценным камням.

 $ bundle show --paths <YOUR $GEM_HOME>/gems/ruby-2.3.0@bundler-test/gems/actioncable-5.0.0 <YOUR $GEM_HOME>/gems/ruby-2.3.0@bundler-test/gems/actionmailer-5.0.0 <YOUR $GEM_HOME>/gems/ruby-2.3.0@bundler-test/gems/actionpack-5.0.0 <YOUR $GEM_HOME>/gems/ruby-2.3.0@bundler-test/gems/actionview-5.0.0 <YOUR $GEM_HOME>/gems/ruby-2.3.0@bundler-test/gems/activejob-5.0.0 ..... 

Я не знал о параметре --paths .

расслоение открыто

bundle open является одной из моих любимых утилит Bundler. Он открывает драгоценный камень в вашем любимом редакторе. Под «любимым редактором» я подразумеваю, какой редактор вы когда-либо $BUNDLER_EDITOR переменных окружения $EDITOR или $BUNDLER_EDITOR .

 $ export EDITOR=vim $ bundle open rake ...opens to the rake gem directory in vim... 

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

комплект устаревший

Я видел несколько постов об bundle outdated , работа которых заключается в том, чтобы просматривать драгоценные камни и сообщать вам, была ли выпущена более новая версия драгоценного камня. Выполнение этого на одном из моих старых проектов заняло несколько минут (буквально) и выглядело так:

 $ bundle outdated Fetching gem metadata from https://rubygems.org/........... Fetching version metadata from https://rubygems.org/... Fetching dependency metadata from https://rubygems.org/.. Resolving dependencies.............................................(lots more dots) Outdated gems included in the bundle: * active_model_serializers (newest 0.10.2 4ff33a7, installed 0.10.0.rc5 63e9337) in group "default" * byebug (newest 9.0.5, installed 8.2.4) in groups "development, test" * committee (newest 1.14.1, installed 1.14.0) in group "default" * database_cleaner (newest 1.5.3, installed 1.5.1) in group "test" ....lots more outdated gems... 

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

 $ bundle outdated rails Resolving dependencies... (again, takes a really long time) 

Есть три параметра командной строки:

  • --local проверит кэш --local без подключения к удаленным источникам (имеется в виду Rubygems).
  • --pre будет включать предварительные релизы, которые по умолчанию исключены.
  • --source проверяет «конкретный источник», который, я полагаю, вы передадите в опцию. Документы на самом деле не говорят, и у меня нет собственного сервера Rubygems.

консоль

Это одна из утилит, о которой я всегда забываю. Запущенная bundle console запустит сеанс IRB со всеми гемами в комплекте, для которых уже require d (если только вы не укажете, что они не требуются в Gemfile).

 $ bundle console irb> Rails => Rails 

Это очень полезно, особенно если вы разрабатываете гем и хотите быстрый REPL со своим гемом и всеми его зависимостями. Кстати, если вы любите Pry (а кто нет?), Вы можете использовать пакетную bundle console config pry pry, чтобы Bundler использовал Pry в качестве консоли, предполагая, что вы уже установили Pry.

блокировка

Вы знаете, как пара командных bundle list и командных показов перестроит файл Gemfile.lock? Ну, это именно то, что делает bundle lock . Он восстанавливает файл блокировки, но не загружает и не устанавливает никаких драгоценных камней:

 $ bundle lock Fetching gem metadata from https://rubygems.org/........... Fetching version metadata from https://rubygems.org/... Fetching dependency metadata from https://rubygems.org/.. Starting resolution (2016-07-27 13:58:05 -0400) Resolving dependencies...Creating possibility state for rails (167 remaining) Attempting to activate rails (5.0.0) Activated rails at rails (5.0.0) Requiring nested dependencies (activesupport (= 5.0.0), actionpack (= 5.0.0), actionview (= 5.0.0), activemodel (= 5.0.0), activerecord (= 5.0.0), actionmailer (= 5.0.0), activejob (= 5.0.0), actioncable (= 5.0.0), railties (= 5.0.0), bundler (< 2.0, >= 1.3.0), sprocket s-rails (>= 2.0.0)) Creating possibility state for bundler (< 2.0, >= 1.3.0) (1 remaining) Attempting to activate bundler (1.11.2) Activated bundler at bundler (1.11.2) Requiring nested dependencies () ... Writing lockfile to /path/Gemfile.lock 

Есть несколько вариантов bundle lock :

  • --lockfile=FILE : записать файл блокировки в FILE . Я не мог заставить это работать, кстати.
  • --local : не подключаться к Rubygems, просто использовать локальный кеш гемов.
  • --print : распечатать файл блокировки в STDOUT.
  • --update=[gems] : обновит список предоставленных gems или все драгоценные камни, если они не указаны. Это агрессивное обновление драгоценных камней.

пучок, а именно

Вот еще одна утилита, которой я никогда не пользовался. bundle viz создает граф зависимостей вашего Gemfile. Давайте взглянем:

 $ bundle viz #<LoadError: cannot load such file -- graphviz> Make sure you have the graphviz ruby gem. You can install it with: `gem install ruby-graphviz` 

О, я думаю, мне нужен gem install ruby-graphviz (что я и делаю):

 $ bundle viz /<path>/gem_graph.png 

Если мы откроем этот файл, он будет выглядеть так:

пучок, а именно

Это для ванильного приложения Rails … неплохо. Я запустил его в одном из моих развернутых проектов, и, мягко говоря, он выглядел более сложным. Тем не менее, это также показало мне, что камень, который мы написали, вероятно, делает слишком много, основываясь на том, что он использует как зависимости. Полезно и стыдно, все сразу.

Есть несколько вариантов:

  • -f или --file позволяет указать имя выходного файла.
  • --format или -F — как выбрать формат изображения (png, jpg, svg и т. д.)
  • --requirements показывает версии каждой требуемой зависимости, которые являются ребрами графа.
  • --version показывает версии драгоценных камней, которые являются узлами графа.
  • И, конечно, --without позволяет исключить группы драгоценных камней из изображения.

жемчужина расслоения

Из всех утилит, bundle gem вероятно, самая большая. Смысл в том, чтобы сгенерировать все файлы, необходимые для начала разработки правильного камня. На самом деле, использование bundle gem — это способ начать новый самоцвет:

 $ bundle gem bundler bundle gem my-new-gem Creating gem 'my-new-gem'... create my-new-gem/Gemfile create my-new-gem/.gitignore create my-new-gem/lib/my/new/gem.rb create my-new-gem/lib/my/new/gem/version.rb create my-new-gem/my-new-gem.gemspec create my-new-gem/Rakefile create my-new-gem/README.md create my-new-gem/bin/console create my-new-gem/bin/setup create my-new-gem/.travis.yml create my-new-gem/.rspec create my-new-gem/spec/spec_helper.rb create my-new-gem/spec/my/new/gem_spec.rb Initializing git repo in /path/my-new-gem 

Вы можете увидеть все, что создала команда:

  • Конечно, мы получаем Gemfile
  • Мы также получаем инициализированный репозиторий git, дополненный .gitignore . О, и все новые файлы git add в индекс.
  • Стандартные файлы gem, включая gemspec, Rakefile, файлы версий, двоичные файлы для console и setup .
  • В моем случае он генерировал файлы RSpec для тестирования. Это означает, что некоторое время назад я запускал bundle gem , мне было предложено выбрать rspec тестирования (RSpec или Minitest) и выбрал rspec .
  • Файл конфигурации Travis CI, который, честно говоря, я понятия не имею, почему он является частью вывода bundle gem по умолчанию. Я чувствую, что должен что-то сделать, чтобы это произошло.

Кроме того, есть пара пунктов, не показанных выше: кодекс поведения и лицензия. Опять же, я должен отказаться от тех, в какой-то момент, когда я bundle gem камни в прошлом.

С точки зрения опций, большинство опций заключается в переопределении создания (или пропуска) частей драгоценного камня. Существуют варианты создания или пропуска следующего: исполняемый файл для --exe ( --exe или --exe --no-exe ), кодекс поведения (RO) ( --coc , --coc --no-coc ), шаблон расширения C ( --ext , --no-ext ), лицензия MIT (RO) ( --mit , --mit --no-mit ).

Единственными двумя другими параметрами являются -e чтобы открыть .gemspec в вашем $EDITOR и --test=TEST (RO), чтобы указать rspec или minitest .

расслоение платформы

bundle platform сообщит вам, какие платформы Ruby вы указали или какие платформы использует ваш гем:

 $ bundle platform Your platform is: x86_64-darwin15 Your app has gems that work on these platforms: * ruby Your Gemfile does not specify a Ruby version requirement. 

Итак, я бегу на Mac, используя МРТ. Если я добавлю ruby "2.3.0" в мой Gemfile, вот что произойдет:

 $ bundle platform our platform is: x86_64-darwin15 Your app has gems that work on these platforms: * ruby Your Gemfile specifies a Ruby version requirement: * ruby 2.3.0 Your current platform satisfies the Ruby version requirement. 

Существует опция --ruby , которая просто возвращает версию Ruby, указанную в Gemfile, если таковая имеется.

чистый комплект

Иногда вы устанавливаете гемы (случайно или специально), которые не используются вашим приложением. Кроме того, если вы используете RVM, в какой-то момент я знаю, что неиспользуемые гемы после установки никогда не удаляются из гемсета. Таким образом, bundle clean позаботится об этом:

 $ bundle clean Cleaning all the gems on your system is dangerous! If you're sure you want to remove every system gem not in this bundle, run `bundle clean --force`. 

Вау, это страшное сообщение. закрывает глаза

 $ bundle clean --force Removing ruby-graphviz (1.2.2) 

Ах, это только что ruby-graphviz гем ruby-graphviz из моего текущего набора гемов, который я установил, чтобы показать вам bundle viz .

расслоение binstubs

Binstubs — это сценарии, которые используются для переноса исполняемых файлов, чтобы установить среду для этого исполняемого файла. Это как шаблон Decorator, но для исполняемых файлов. Если вы когда-нибудь запускали bundle exec <some command> , это почти то же самое. Bundler достаточно любезен, чтобы предложить bundler binstub <a gem in the bundle> чтобы сгенерировать файл, который вы можете вызвать, который упаковывает вещи по мере необходимости:

 $ bundle binstubs rack 

Это создаст каталог bin и напишет binstubs для всех исполняемых файлов в геме стойки. В этом случае есть только один ( rackup ). Итак, теперь мы можем вызвать bin/rackup и он будет запущен в контексте нашего пакета.

Кстати, если вы запустите bundle install --binstubs (RO) , то Bundler сгенерирует binstub для каждого гема с исполняемыми файлами при каждой bundle install .

пучок инъекций

Это странно. bundle inject принимает имя и версию гема и внедряет их в Gemfile и Gemfile.lock:

 $ bundle inject rspec ">0" ...performs resolution... Added to Gemfile: rspec (> 0) 

rspec не устанавливается до тех пор, пока не будет запущена bundle install . Я понятия не имею, почему кто-то будет использовать это, но держу пари, что есть веская причина (пожалуйста, сообщите нам в комментариях, если вы знаете, что это такое)

версия пакета

Для полноты картины есть bundle version в bundle version :

 $ bundle version Bundler version 1.12.5 

Кстати, 1.12.5 является последней версией Bundler на момент написания этой статьи? Какую версию вы используете? Могу поспорить, что некоторые из вас не обновили Bundler за долгое время …

Выполнено

Это вкратце утилиты Bundler. Что ж, если под «ореховой скорлупой» я подразумеваю «отчасти дольше, чем я намеревался написать в блоге». Тем не менее, я узнал довольно много вещей и, вероятно, кое-что понял неправильно. Итак, если вы видите ошибку, дайте мне знать. Идите вперед и расслоение.