Web Marina

日々の業務や勉強などで得た知識をアウトプットしていきます。

binって何?railsとrakeって何?(前編)

f:id:song-of-life1352607:20170411225447p:plain

こんにちは、マリンです。


アプリ開発していてわからないことがあると私はまずグーグル先生に聞きます。 多分大体の方がそうだと思いますが・・・

すると頻繁にこんな一文を見かけますよね。

$bin/rails ~

このbinって何だろうな?ってずっと気になっていたんですよね。


アプリの中にそういうディレクトリがあるのも知ってたんですが、詳細とか何が書かれているのかは今までスルーしてきました。(余計なこと調べるとハマるのでw)


でも今は取り急ぎやっていることもないので、いい機会だから調べてみました。

内容

binてよく見かけるけど、ついてる時とついてないときあるし、ついでにbin/railsとかbin/rakeとかあるけど・・・

binて何だ?railsrakeの違いってなんだ??について書こうと思います。

解説

binファイルとは?

まずはざっくりbinファイルってなんなのか調べてみました。

よくお世話になるIT用語辞典 e-Wordsさんではこのように書かれていました。

BINファイルとは、ファイル形式・拡張子の一つだが、標準化されたデータ形式ではなく、アプリケーション独自の形式で保存されたバイナリデータのファイル名の拡張子などによく使われる。“bin”は「バイナリ」(binary)の略号で、テキスト形式ではなくバイナリ形式であることを示している。

まだちょっと難しいですね。


こちらのサイト様でもっと簡単に書かれていました。(こちらもよくお世話になっております。)

wa3.i-3-i.info

binファイルとは通常バイナリデータが書かれていることが多いファイルで、バイナリデータというのはコンピュータが理解するためのプログラムが書かれたファイルということですか。


私はこの「バイナリデータ」の認識が間違っていたようですね。

画像とか音声を扱うファイルと思っていましたw

Railsアプリの中のbinディレクト

Rails Tutorialの1.3 最初のアプリケーションでは各ディレクトリのざっくりとした用途が書かれています。

bin/ バイナリ実行可能ファイル

やはりRailsに置いてもその用途は同じようですね。

binディレクトリの中身

ディレクトリの中身はこのようになっています。

bin/
┣bundle
rails
┣rake
┣setup
┣spring
┣update

bin/rails

今回はrailsコマンドとrakeコマンドの違いを知りたいので、その他のファイルは省略します。

なお、これ以降の内容はRailsガイドの「Railsの初期化プロセス」の中に詳しく書かれています。 railsguides.jp

あとこちらの記事も参考にさせていただきました。 shgam.hatenadiary.jp




bin/railsファイルの中身は以下のようになっています。

#!/usr/bin/env ruby
begin
  load File.expand_path('../spring', __FILE__)
rescue LoadError => e
  raise unless e.message.include?('spring')
end
APP_PATH = File.expand_path('../config/application', __dir__)
require_relative '../config/boot'
require 'rails/commands'
  • #!/usr/bin/env ruby
    • #!は「shebang(シバン)」といい、インタプリタを指定するための文を表します。railsと言うファイルをrubyで解釈して欲しいので、この場合/usr/bin/env rubyという文でrubyインタプリタを使用することを指示しています。


  • begin~rescue~end
    • この間は例外処理です。springファイルがLoadErrorになった場合の処理のようです。


  • APP_PATH~
    • APP_PATHにパスを入れています。このあとに呼び出されるrails/commandsの中で使用されるようです。

    • File.expand_pathは、相対パス絶対パスに変換してくれます。第2引数の__dir__相対パスの基準となるディレクトリです。


  • require_relative'config/boot.rb'
    • require_relativeとすることで、ファイルの相対パスを指定して読み込むことができるそうです。

<boot.rbの中身>

ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)

require 'bundler/setup' # Set up gems listed in the Gemfile. 
  • ENV[~
    • 環境変数BUNDLE_GEMFILEにGemfileのパスを入れています。 ||=が付いているので、「もし入っていなければ入れる」という指示です。
  • require~
    • bundler/setuprequireします。
    • このbundler/setupは、Gemfileにある依存ファイルが置かれている読み込みパスをBundlerで設定する際に使用されます。

つまり、このboot.rbファイルで、Gemfile内のGemをBundlerでセットアップをする指示を出しているということでしょうか・・・


ちなみに、RailsガイドではrequireがGemfileが存在する場合に実行されるようif文によって書かれていますが、私のファイルにはなかったです。 Gemfileが存在しないってことがまずないから無くなったのでしょうか??


bin/railsに戻って、 * require'rails/commands' * boot.rbファイルの次はcommands.rbファイルがrequireされます。 * このファイルにはコマンドの別名を拡張するためのコードが書かれています。つまり、serversと略せるようになるのはこのファイルのおかげです。

ARGV << '--help' if ARGV.empty?
 
aliases = {
  "g"  => "generate",
  "d"  => "destroy",
  "c"  => "console"
  "s"  => "server",
  "db" => "dbconsole"
  "r"  => "runner"
}
 
command = ARGV.shift
command = aliases[command] || command
 
require 'rails/commands/commands_tasks'
 
Rails::CommandsTasks.new(ARGV).run_command!(command)

コマンドの省略形に対する処理をした後、コマンドを実行する流れのようです。


長くなってきたので、続きは次回にします。

これまでの内容で誤りがありましたら是非ご指摘ください。