A Gemfile describes the gem dependencies required to execute associated Ruby code.
参照: https://guides.rubygems.org/gemfile/
対象のRubyコードを実行するために必要な依存gemを記述するファイル。対象のコードを含むディレクトリのルートディレクトリに配置する。
例えば、RailsだとRakefileが存在するディレクトリに配置されている。
The .gemspec file is where you provide metadata about your gem to Rubygems. Some required Gemspec attributes include the name, description, and homepage of your gem. This is also where you specify the dependencies your gem needs to run.
参照: https://guides.rubygems.org/gemfile/
RubyGemsにgemについてのメタデータを提供するためのファイル(.gemspec)。
gemの名前や概要などの基本情報に加えて、gemの実行に必要な依存についても定義できる。
gemの開発時にBundlerを使って、開発に必要な依存gemの管理をしたいとする。
もちろんGemfileで依存関係を管理できるが、Gemfileからgemspecメソッドを呼び出すことで、.gemspecファイルに定義されている依存関係のリストに基づいた依存の解決ができる。
.gemspecには、用途に応じて以下のように依存関係を定義する。
add_dependency: gemの実行に必要な依存add_development_dependency: gemの開発時のみ必要な依存
rspec, rubocopなどここまででGemfileへの依存gemの定義方法が2通りあり、Gemfileの機能としてgemメソッドによる直接的な定義方法と、gemspecメソッドにより.gemspecの定義内容を間接的に参照する方法があることがわかった。
Webアプリケーションのようにgemとして公開しない場合は、通常.gemspecファイルを作成することはない。Gemfileにgemメソッドを使用して依存を定義していけばよい。
では、gemを開発する場合にどのように定義場所を決めればよいか?
基本はClarifying the Roles of the .gemspec and Gemfileにあるように.gemspecファイルに依存関係の定義を集約し、依存関係の重複定義を避ける。
Gemfileは、以下のようにgemspecメソッドのみを呼び出す形にする。
# frozen_string_literal: true
source "https://rubygems.org"
# Specify your gem's dependencies in heroku-review-apps-manager.gemspec
gemspec
.gemspec内で、以下のように依存関係を定義する。
Gem::Specification.new do |spec|
# ...
spec.add_dependency "faraday"
spec.add_dependency "octokit"
spec.add_dependency "thor"
spec.add_development_dependency "rake"
spec.add_development_dependency "rspec"
spec.add_development_dependency "rubocop"
spec.add_development_dependency "webmock"
end
とはいえ正解はなく、実際の運用方針はプロジェクトやメンテナによって分かれるようです。
色々調べてみた結果、Gemfileでしかできない定義の方法もあるので、個人的には.gemspecに集約することを基本方針とし、Gemfile側に定義する必要が出たものだけをGemfileに書くという以下のスタイルがよさそうだと考えている。
※ group, platforms, source, git, pathなどはGemfileでしか定義できない