Статьи

Gemfile Mining: Погружение в Gemfile Бандлера

Bundler

Bundler просто великолепен, поэтому он стал де-факто менеджером пакетов и зависимостей для приложений на Ruby. Я использовал npm и golang vendoring и другие менеджеры языковых зависимостей, но ни один из них даже не может удержать свечу от той простоты, которую предлагает Bundler.

Как я уверен, вы знаете, в основе доброты Бундлера лежит Gemfile . Gemfile содержит список драгоценных камней, которые необходимы нашему приложению для выполнения своей работы. Если вы похожи на меня, я научился использовать Gemfile и Bundler из различных руководств по Rails (и другим). Я видел, как люди печатали

  gem "a_gem"

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

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

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

Основы

Всегда хорошее место для начала, это то, что вы, вероятно, уже знаете.

Источник

В верхней части всех Gemfiles есть строка вроде этой:

 source "https://rubygems.org"

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

  • Вы можете иметь несколько строк sourceобратном порядке, в котором они перечислены. Мне это не очень нравится, но оно есть.
  • Если вы используете частный гем-сервер, вам нужно установить имя пользователя и пароль, используя source Не кладите его в GEMFILE, потому что он окажется на Github, и тогда ваши личные жемчужины станут открытыми, и наступит хаос.
  • Хорошо, вы можете поместить пользователя и пароль в сам URL ( bundle config В любом случае, ты собираешься это сделать? разглагольствовать о том, что молодые люди никогда не слушают

Драгоценные камни

Правильно. Мы все знаем, как указать драгоценный камень в Gemfile, верно?

 https://user:pass@gem.server.com

Эта линия будет тянуть в последней версии драгоценного камня. Очевидно, вы должны заблокировать свои зависимости для версий, которые, как вы знаете, работают с вашим приложением. Есть несколько способов указать версии гемов:

  • Используйте конкретную версию: gem "name-of-gem"
    Вы можете найти конкретные версии на Rubygems.org (при условии, что это gem "name-of-gem", "1.0"выполнив поиск вашего драгоценного камня и просмотрев перечисленные «Версии».
  • Используйте оператор версии: source Это тянет в любой драгоценный камень, который после 1.0.
  • Используйте этот странный оператор squiggly-stabby: gem "name-of-gem", ">1.0" Этот оператор, который некоторые называют «тиддл-чёрт», в основном говорит «любая версия больше этой, но меньше следующей незначительной ревизии». Поскольку я уверен, что вы знаете, что такое семантическое управление версиями , мне не нужно объяснять, что второстепенная версия — это второе число. В этом примере это означает «любая версия больше или равна 1,3, но меньше 1,4». Он также работает с основными версиями, поэтому gem "name-of-gem", "~>1.3"~>12~>1.0.rc.1
  • Используйте составное требование: 1.0.rc Здесь мы хотим конкретную версию, но все в порядке с более новыми незначительными выпусками Никто не делает это.

группы

Bundler позволяет вам распределить ваши зависимости в разные группы. Это чаще всего используется для установки в среду разработки других драгоценных камней, чем те, которые установлены в производственной среде. Вы можете указать группы для драгоценного камня в той же строке, что и драгоценный камень, или поместив драгоценный камень в gem "name-of-gem", "~>2.2", ">=2.2.1"

 group

Затем вы можете избежать установки определенной группы (или групп) в определенную среду, используя gem "my-dev-tool", group: :development

group :development, :test do
gem "my-test-tool"
end
--withoutbundle install

Редкие Находки

Давайте поговорим о других вариантах указания драгоценных камней, которые вы могли видеть или не видеть, но, вероятно, не совсем понятны. По крайней мере, я так к ним отношусь.

платформы

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

 gem "my-java-gem", platform: jruby

Если я bundlemy-java-gem

install_if

Другой способ контролировать установку гема — это install_if Передача proc или лямбда-выражения с логическим значением (что означает «правдивый» или «ложный») будет контролировать установку драгоценных камней в блоке. Из документов:

 install_if -> { RUBY_PLATFORM =~ /darwin/ } do
  gem "pasteboard"
end

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

требовать

Если вы когда-либо видели ключевое слово require

 gem "rspec", require: "spec"

Это означает, что имя драгоценного камня и имя, по которому вам требуется драгоценный камень, различны. Видите ли, когда что-то вызывает Bundler.require Итак, в примере вы хотите, чтобы он require "spec"require "rspec"

Также иногда мы видим такую ​​строку:

 gem 'rspec', require: false

Это говорит Bundler не требовать rspecBundler.require Например, Rails вызовет Bundler.require

Bundler по умолчанию установит все гемы в Gemfile и загрузит их в память. Если мы не хотим загружать определенный гем (возможно, потому что мы будем делать это динамически из нашего кода), мы можем установить для ключевого слова require значение false.

Переопределить источник

Я упомянул ключевое слово sourcesource Это может быть сделано на основе одного драгоценного камня или для нескольких драгоценных камней в блоке:

 gem "a-gem", source: "https://my-private-gem-server.com" 

source "https://my-private-gem-server.com" do
  gem "a-gem"
  gem "b-gem"
end

Гит

Другой, более распространенный способ переопределить источник гемов — использовать параметры gitgithubpath

Когда вы извлекаете гем непосредственно из git, нужно просто указать путь к хранилищу:

 gem "my-git-gem", git: "https://github.com/me/my-git-gem.git"

У вас должен быть доступ к репо, поэтому он должен быть общедоступным, в вашей сети и т. Д. Синтаксис блока также работает, если ваш репозиторий git имеет более одной gemspec:

 git "http://github.com/me/many_gems.git" do
  gem "a-gem"
  gem "b-gem"
end

Кстати, эти репозитории должны иметь файлы .gemspec В противном случае вы должны предоставить версию:

 gem "my-git-gem-with-on-spec", "0.1", git: "https://github.com/me/my-git-gem-with-no-spec.git"

Что если вы хотите добавить ветку, тег или конкретный коммит? Bundler позволяет вам использовать параметры branchtagref

 gem "my-git-gem", git: "https://github.com/me/my-git-gem.git", branch: "the_new_stuff"
gem "my-git-gem", git: "https://github.com/me/my-git-gem.git", tag: "1.0.rc2"
gem "my-git-gem", git: "https://github.com/me/my-git-gem.git", ref: "5acdb"

Кстати, опция ref

Наконец, если вы используете git-репозиторий, в котором есть множество субмодулей (люди так делают?), Существует логическая опция submodule

 gem "my-gem-of-submodules", git: "https://github.com/me/my-gem-of-submodules.git", submodules: true

Пользовательские источники Git

Как выяснилось, вы можете определить собственные источники git. Bundler предоставляет 3 исходных git-источника: githubbitbucketgist Это обеспечивает довольно классное сокращение:

 gem "my-git-gem", github: "me/my-git-gem.git"

Просто укажите путь к репо на Github (или Bitbucket). Что если владелец (или организация) имеет то же имя, что и хранилище git? Это становится еще меньше:

 gem "rails", github: "rails" # Works b/c the repo is https://github.com/rails/rails.git

Все параметры, которые работают для исходного кода git Кстати, опция githubgit

Если ваши репозитории на Github являются частными, вы можете создать токен личного доступа и использовать его в Gemfile:

 gem "my-private-gem", git: "https://<the_token>:x-oauth-basic@github.com/me/my-private-gem.git"

Это облегчает использование частных git-репозиториев, но размещение вашего токена в Gemfile — это путь к катастрофе. Чтобы обеспечить безопасность вашего токена, установите переменную окружения ( GITHUB_TOKENgitgem "my-private-gem", git: "https://#{ENV['GITHUB_TOKEN']}:x-oauth-basic@github.com/me/my-private-gem.git"

 bundle config

С большой любовью к этой сути, для того, чтобы сначала показать это мне. К сожалению, все еще существует проблема с этим подходом, так как он запишет токен в файл Gemfile.lock , который, вероятно, находится под контролем исходного кода. Так что мы можем сделать?

Существует также способ использовать gem "my-private-gem", git: "https://github.com/me/my-private-gem.git"
Если вы измените строку в вашем Gemfile на:

 bundle config github.com <the_token>

а потом беги

 ~/.bundle/config

Bundler будет использовать токен для доступа к github от вашего имени. Итак, все ваши личные репо будут доступны. Кстати, это записывает значения в gem "gist-gem", gist: "e0bef10af2e0f9bb2ed703c721ca9d29"
Хммм … может быть, мне нужно сделать еще одну статью, которая погружается в CLI Bundler. разглагольствовать о том, что моя работа никогда не делается

Суть

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

 git_source(:stash){ |repo_name| "https://stash.corp.acme.pl/#{repo_name}.git" }
gem "rails", :stash => "forks/rails"

Это работает. Пока это. Я понятия не имею, почему кто-то сделал бы это. Но я тоже не получаю MySpace.

Наконец, вы можете создавать собственные источники git для других git-серверов, таких как Github Enterprise Server, Bitbucket Server (формально Stash) или других источников. Вот пример из документации:

 path

Путь

Если у вас есть гем, который вы разрабатываете локально, вы можете добавить его в свой пакет с помощью опции gem "mine-mine-all-mine", path: "~/my-gems/mine-mine-all-mine"

 path "~/my-gems" do
  gem "mine-mine-all-mine"
  gem "acts-as-myspace"
end

Конечно, есть опция блока:

 ruby "~>2.1"

Версия Ruby

Можно указать версию Ruby и интерпретатор (или движок), которые требуются вашему приложению. Например, если вы связаны с Ruby 2.1 или выше, но не хотите предполагать, что 2.2 в порядке, поместите это в верхнюю часть вашего Gemfile:

 ruby "~>2.1", engine: "jruby", engine_version: "9.0.3.0"

Эта версия, очевидно, относится к МРТ по умолчанию. Что делать, если вы хотите захватить JRuby?

 ruby

Это означает, что вам нужен JRuby 9000. Ключевое слово patchlevel Кстати, если я когда-нибудь отправлю патч, это будет nicotineadamseye

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

Все сделано

Итак, это все. Bundler Gemfile дистиллированный. Кто знал, что в Gemfile так много вариантов установки гемов? Я этого не сделал, поэтому эти усилия научили меня новым вещам и подтвердили мою любовь к Бандлеру, лучшему менеджеру по зависимостям в мире. Я надеюсь, вы тоже чему-то научились.

Вот вам вопрос: я что-то пропустил? Любые другие уловки, которые мы должны включить сюда? Что молодые люди делают с Bundler в эти дни?

Я хотел бы искренне поблагодарить Энрике Гонсалеса и Фреда Хита за рецензирование этой статьи. Несмотря на молодость, они очень полезные члены общества.