Movatterモバイル変換


[0]ホーム

URL:


LoginSignup
13

Go to list of users who liked

15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

rails new の流れを追う

Last updated atPosted at 2014-05-08

環境

  • ruby 2.1.1p76
  • Rails 4.1.1

railsコマンド

ふとrails newした時の流れが気になったので・・・
まずはrailsコマンドの在処を調べて、ファイルの中身を確認します。

$which rails/Users/usutani/.rvm/gems/ruby-2.1.1@rails411/bin/rails$cat`which rails`

ファイル先頭のコメント部を確認すると・・・

path/to/bin/rails
# !/usr/bin/env ruby_executable_hooks## このファイルはRubyGemsによって生成されました。## アプリケーションrailtiesはgemの一部としてインストールされ、# このファイルはその実行を容易にするためここにあります。#

とのこと。ファイルの続きは・・・

path/to/bin/rails
require'rubygems'version=">= 0"ifARGV.firststr=ARGV.firststr=str.dup.force_encoding("BINARY")ifstr.respond_to?:force_encodingifstr=~/\A_(.*)_\z/andGem::Version.correct?($1)thenversion=$1ARGV.shiftendendgem'railties',versionloadGem.bin_path('railties','rails',version)

if文のブロックでrails _4.1.1_ newのように第一引数にバージョンが指定された場合に対応する。

指定したバージョンのrailtiesが無ければGem::LoadErrorで終了する。

最後に、バージョンを指定してrailtiesのrailsをロードする。requireでないのは二度目以降も読み込むため。

バージョンを指定しない場合の振る舞いをirbで試してみると・・・

irb
>gem'railties',">= 0"=>true>loadGem.bin_path('railties','rails',">= 0")Usage:railsnewAPP_PATH[options]...>Gem.bin_path('railties','rails',">= 0")=>"/Users/usutani/.rvm/gems/ruby-2.1.1@rails411/gems/railties-4.1.1/bin/rails"

ロードしているrailtiesのbinディレクトリに存在するrailsファイルの中身を確認します。

railties-4.1.1/bin/rails
# !/usr/bin/env rubygit_path=File.expand_path('../../../.git',__FILE__)ifFile.exist?(git_path)railties_path=File.expand_path('../../lib',__FILE__)$:.unshift(railties_path)endrequire"rails/cli"

railtiesディレクトリの上位に.git ディレクトリが存在すれば、自身を優先してロードされるように探索パス$:(組み込み変数)にlibを追加してから、rails/cliをロードしています。

railties/lib

cli.rb

lib/rails/cli.rb
require'rails/app_rails_loader'# アプリのrailsコマンドで実行した場合は、残りのスクリプトは実行されません。Rails::AppRailsLoader.exec_app_rails

今はアプリ外のrailsコマンドを実行しているので、残り(下記)のスクリプトが実行されます。

lib/rails/cli.rb
require'rails/ruby_version_check'Signal.trap("INT"){puts;exit(1)}ifARGV.first=='plugin'ARGV.shiftrequire'rails/commands/plugin'elserequire'rails/commands/application'end

Ctrl + Cが押されたら、プログラムを異常終了する。
rails newの場合なので、else節に入りrails/commands/applicationがロードされる。

Generators

続けてrails/commands/application.rbを確認します。

rails/commands/application.rb
require'rails/generators'require'rails/generators/rails/app/app_generator'moduleRailsmoduleGeneratorsclassAppGenerator# :nodoc:# We want to exit on failure to be kind to other libraries# This is only when accessing via CLIdefself.exit_on_failure?trueendendendendargs=Rails::Generators::ARGVScrubber.new(ARGV).prepare!Rails::Generators::AppGenerator.startargs

Generatorは、Rails 3.0からThorをベースにしています。

exit_on_failure?をオーバライドして、失敗時に異常終了させる。
引数を準備して、Generators::AppGeneratorを開始する。

app_generator.rbの外観は次のようになります:

rails/generators/rails/app/app_generator.rb
require'rails/generators/app_base'moduleRailsmoduleActionMethods# :nodoc:...# application builderはapplication generatorの要素を上書きできます。## Gemfile、READMEやJavaScriptファイルの作成のなどのように、あなたは全体の操作を上書きでき# ます。これらの操作を正確に把握していなくても、別のテンプレートアクションを作成できます。classAppBuilder...moduleGenerators...classAppGenerator<AppBase# :nodoc:...# このクラスはAppGeneratorが呼ばれる前に引数を準備します。このクラスはバージョンやヘルプ情# 報を求められれば提供し、(追加の設定オプションに用いる)railsrcファイルも構成します。## このクラスはARGVを設定し正しく変化させるため、AppGeneratorの開始前に、このクラスを呼び# 出す必要があります。classARGVScrubber# :nodoc...defprepare!

AppBuilder
このクラスのメソッドで、アプリ内のディレクトリ作成やファイルのコピーなどを行っています。

AppGenerator
AppBuilderとの関係が気になるので調べてみると、get_builder_classメソッドからAppBuilderを呼び出していました。

rails/generators/rails/app/app_generator.rb
moduleGenerators...classAppGenerator<AppBase# :nodoc:...defget_builder_classdefined?(::AppBuilder)?::AppBuilder:Rails::AppBuilderend

このget_builder_classを呼んでいるのは、親クラスAppBaseです。

rails/generators/app_base.rb
moduleRailsmoduleGeneratorsclassAppBase<Base# :nodoc:...protected...defbuilder@builder||=beginbuilder_class=get_builder_classbuilder_class.send(:include,ActionMethods)builder_class.new(self)endend

これらの関係を図示すると次のようになります:

generators.png

Thor::Groupを派生したAppGeneratorクラスは、定義されたメソッドを順番に実行していきます。

rails/generators/rails/app/app_generator.rb
defcreate_root_filesdefcreate_app_filesdefcreate_bin_filesdefcreate_config_filesdefcreate_boot_filedefcreate_active_record_files...

create_root_filesメソッド内のbuildの呼び出しに注目してみると、

rails/generators/rails/app/app_generator.rb
defcreate_root_filesbuild(:readme)...

buildはAppBaseで定義されていて、builder=AppBuilderのreadmeを呼んでいます。

rails/generators/app_base.rb
defbuild(meth,*args)builder.send(meth,*args)ifbuilder.respond_to?(meth)end
rails/generators/rails/app/app_generator.rb
classAppBuilder...defreadmecopy_file"README.rdoc","README.rdoc"end
13

Go to list of users who liked

15
0

Go to list of comments

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13

Go to list of users who liked

15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?


[8]ページ先頭

©2009-2025 Movatter.jp