Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

【完全ガイド】RubyのGems・Gemfile・Bundlerを徹底解説

Ruby開発において「gem」という言葉は避けて通れません。この記事では、Ruby gemの基本概念から、実際にgemを作る方法、GemfileとBundlerの使い方まで、体系的に解説します。

Ruby gemとは?

gemとは、ダウンロードしてインストールできるパッケージのことです。インストール済みのgemをrequireすると、Rubyプログラムに新しい機能を追加できます。

gemでできること

  • Railsアプリにログイン機能を追加する
  • 外部サービス(APIなど)との連携を簡単に実現する
  • Webアプリケーションを構築する

これはほんの一例です。すべてのgemにはそれぞれ固有の目的があります。

なぜgemを使うのか

  • Rubyでライブラリやツールを共有するための標準的な仕組みだから
  • gemのファイル構成やフォーマットが統一されており、仕組みが理解しやすいから
  • 各gemに付属するspecファイル(.spec)が依存関係(必要な他のgem)を記述しているため、コードが動作に必要なものをすべて揃えられるから

RubyGemsのおかげで、私たちは充実したライブラリのエコシステムを利用でき、あとはgem install一つで導入できます。

また、プロジェクトで必要なgemの一覧は「Gemfile」という特別なファイルに記述でき、Bundlerを使って自動インストールすることも可能です。これらについては後ほど詳しく説明します。

代表的なgemの例

  • Rails:ActiveRecordやActiveSupportなど、すべてのコンポーネントがRuby gemとして配布されています
  • Pry:irbの強力な代替となる対話型シェル
  • Nokogiri:人気のXML・HTMLパーサー

ほとんどのgemは純粋なRubyコードで書かれています。一部のgemはパフォーマンス向上のためC拡張(Ruby C extension)を含んでおり、これはgemのインストール時に自動的にビルドされます。ただし場合によっては、RubyGemsが管理していない追加ソフトウェアの手動インストールが必要になることもあります。

それでは、実際に自分でgemを作りながら、その構造を詳しく見ていきましょう。

RubyGemの作り方

新しいgemの雛形ファイルは、bundle gem <name>コマンドで生成できます。

bundle gem awesome_gem

生成されるgemは次のような構造になっています。

├── awesome_gem.gemspec
├── bin
│   ├── console
│   └── setup
├── Gemfile
├── lib
│   ├── awesome_gem
│   │   └── version.rb
│   └── awesome_gem.rb
├── Rakefile
├── README.md
└── test
    ├── awesome_gem_test.rb
    └── test_helper.rb

.gemspecファイルには、そのgemに関するすべての情報が記述されています。

gemspecに含まれる情報

  • gem名
  • 概要(短い説明文)
  • 作者名
  • 依存関係の一覧
  • gemに含めるファイルの一覧
  • 任意項目:作者のメールアドレス、プロジェクトURL(ホームページ)、実行ファイル、C拡張、詳細な説明など

gemのバージョン自体は、lib/<gem_name>/version.rb内で定数として定義されます。

gemspecの記述例

Gem::Specification.new do |spec|
  spec.name          = "awesome_gem"
  spec.version       = AwesomeGem::VERSION
  spec.authors       = ["Jesus Castello"]
  spec.summary       = "Example gem for article about Ruby gems"

  spec.files         = Dir['**/**'].grep_v(/.gem$/)

  spec.require_paths = ["lib"]

  spec.add_development_dependency "bundler", "~> 1.16"
  spec.add_development_dependency "rake", "~> 10.0"
  spec.add_development_dependency "minitest", "~> 5.0"
end

require_paths配列は、gemをrequireしたときにRubyがファイルを探す場所を指定します。これにより、コードをlib/<gem_name>/以下に配置し、require "<gem_name>/<file_name>"という形式で読み込めます。

例:

lib/awesome_gem/parser.rbというファイルは、gem内のどこからでもrequire "awesome_gem/parser"として読み込めます。

多くのrequire文はlib/<gem_name>.rb/lib直下にある唯一のファイル)にまとめて記述します。gemをrequireしたときに読み込まれるのは、まさにこのファイルです。

依存関係の定義方法

add_development_dependencyは、開発時にのみ使うgem(minitest、RSpec、pryなど)を定義します。一方、add_dependencyは、gemのコードそのものが動作に使うgemを定義します。

summaryやdescriptionをデフォルト値から変更すれば、bundle gemが自動生成するbin/consoleプログラムを使って、自分のgemを読み込んだirbセッションを起動できます。

$ bin/console

irb(main):001:0>
irb(main):002:0>
irb(main):003:0> AwesomeGem
=> AwesomeGem
irb(main):004:0>
irb(main):005:0> AwesomeGem::VERSION
=> "0.1.0"

その後、gem build <name>.gemspecでgemをパッケージ化し、gem pushでrubygems.orgへ公開できます。

Bundlerとは?

Ruby gemについて学んでいると、必ずBundlerという名前を目にします。では、Bundlerとは正確には何なのでしょうか?

Bundlerは依存関係管理ツールです。「RubyGemsがすでにその役割を果たしているのでは?」と思うかもしれません。確かにそうですが、RubyGemsが扱えるのはgem自身の依存関係だけです。

通常のRubyアプリケーションはgemとして作られるわけではないため、この仕組みの恩恵を受けられません。そこでBundlerの出番というわけです!

Gemfileの基本を理解する

Gemfileというファイルを見たことがあるでしょうか?ここには、あなたのRubyアプリケーションで使いたいgemを記述します。ここに書かれたgemは、いちいちrequireしなくても自動的に読み込まれます。

Gemfileの記述例

ruby '2.5.0'

gem 'rails', '~> 5.2.1'
gem 'sqlite3'
gem 'puma', '~> 3.11'
gem 'bootsnap', '>= 1.1.0', require: false

Bundler(およびバージョン2.0以降のRubyGems)はこのファイルを読み取り、要求されたバージョンのgemをインストールします。bundle installコマンドを実行すると、次のような出力が表示されます。

Using turbolinks-source 5.1.0
Using turbolinks 5.1.1
Using uglifier 4.1.18
Using web-console 3.6.2

Bundle complete! 18 Gemfile dependencies, 78 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

バージョン指定の意味を理解する

Gemfileで各gemのバージョンを宣言するときに使われる~>などの記号は何を意味しているのでしょうか?これらはバージョンの範囲を指定するためのものです。

たとえば「1.2以上2.0未満のバージョンが欲しい」という条件は、次のように書けます。

gem 'puma', '~> 1.2'

~>この範囲指定のショートカットです。

gem 'puma', '>= 1.2', '< 2.0'

~> 5.2.1の場合、意味するところは正確には次の通りです。

'>= 5.2.1', '< 5.3'

バージョン番号が具体的であるほど、許容されるバージョンの範囲は狭くなります。

GemfileのオプションとGemfile.lock

Gemfile内でgemを指定する際には、いくつかのオプションが使えます。

GitHubからgemを取得する

たとえば、rubygems.orgでまだリリースされていない最新版を使いたい場合などに、GitHubなど別のソースからgemを取得できます。

gem "rails", git: "git@github.com:rails/rails.git"

branchオプションを渡せば、master以外のブランチのコードを利用することも可能です。

gem "awesome_print", git: "git@github.com:awesome-print/awesome_print.git", branch: "v2"

require: falseオプション

もう一つよく見かけるのがrequire: falseです。これは何をするのでしょうか?

このオプションを付けると、Bundlerによるgemの自動読み込みが無効になります。つまり、必要なときにコード内で明示的にrequireしなければなりません。

これは、特定のrakeタスクでのみ使い、Railsのコントローラやモデルでは使わないような、用途が限定的なgemに有効です。必要なときだけgemを読み込むことで、アプリのメモリ使用量を節約できるのがメリットです。

環境ごとのグループ分け

gemを環境ごとにグループ化することもできます。たとえば、development環境でのみインストール・読み込みされるgem(capybarapryなど)を定義できます。

Gemfile.lockの役割

最後に、BundlerはGemfile.lockを生成します。これは何が違うのでしょうか?

Gemfile.lock自動生成されるファイルで、実際にインストールされた各gemの正確なバージョンが記録されています。Bundlerはこのバージョンに従ってインストールを行うため、本番環境へのデプロイ時や他の開発者とのプロジェクト共有時にも、全員がまったく同じgemセットで作業できるようになります。

覚えておきたいgem・Bundlerコマンド一覧

コマンド 説明
gem list インストール済みの全gemを一覧表示。引数で名前による絞り込みも可能(例:gem list active
gem which <name> gemがインストールされているパスを表示
gem search <name> 設定済みのソース(デフォルト:rubygems.org)からgemを検索。正規表現が使える(例:gem search "\Aawesome_"
gem env gem環境に関する情報(バージョン、パス、設定など)を表示
gem install <name> -v <version> 特定のバージョンのgemをインストール(例:gem install sinatra -v 2.0.0
bundle viz 現在のプロジェクトの依存関係グラフを可視化して生成
bundle show Bundler経由でインストールされた特定のgemの情報を表示。Gemfileがあるフォルダ内で実行する必要あり
bundle outdated 現在のプロジェクトで古くなったgemの一覧を表示。--groupsオプションでグループ化も可能
bundle console 現在のプロジェクトのGemfileにあるgemを読み込んだirbセッションを起動

まとめ

この記事では、RubyのパッケージシステムであるRubyGemsについて学びました。さらに、gemの構造、Gemfileとは何か、Bundlerの役割、そしてGemfileGemfile.lockの違いまでを解説しました。

これらの知識を活かせば、ライブラリの管理や独自gemの公開がぐっと楽になるはずです。ぜひ実際に手を動かして試してみてください。

  1. Ruby開発者のための時間計算量とBig O記法 徹底解説ガイド

    時間計算量は、コンピュータサイエンスの中でも最も興味深い概念のひとつです。しかも、特別な学位がなくても十分に理解できます。 この概念が面白いのは、あるアルゴリズムやプログラムがなぜ遅いのかを見抜き、どうすれば高速化できるのかを明確にしてくれる点にあります。 もちろん、自分が書いたコードにもすぐに応用できます。 さらに、教科書に載っているような高度なアルゴリズムだけではなく、日常的に書くコードにも役立つのがポイントです。本記事の後半で実際に確認していきます。 まずは、「遅い」と「速い」の定義から整理しましょう。 「遅い」と「速い」の定義 100万個の数字を150ミリ秒(ms)でソートするのは、果

  2. MacでAndroidメッセージを使いこなす完全ガイド

    AndroidのメッセージをMacで使う?一見不可能に思えますよね。両ブランドは熾烈な競争関係にあるため、「AndroidとMacは相性が悪い」と考える人がほとんどです。しかし、Googleはユーザーにとってより便利で柔軟なコミュニケーション環境を実現するため、Android Messagesを開発しました。 このメッセージングプラットフォームは、Windows PCとMacの両方で利用できます。そのため、Macユーザーでも難しく考える必要はありません。Android Messagesは複数のデバイス間で互換性があるため、さまざまなブランドのガジェットを持つユーザーにとって理想的な選択肢となっ