12
Go to list of users who liked
13
More than 5 years have passed since last update.
環境
- ruby 2.1.1p76
- Rails 4.1.1
rails console
した時のように、アプリ内のrailsコマンドを実行した時の流れを追ってみました。
exec_app_rails
rails new
と同じ処理の流れで、exec_app_railsを呼び出します。
lib/rails/cli.rb
require'rails/app_rails_loader'Rails::AppRailsLoader.exec_app_rails
rails/app_rails_loader.rb
moduleRailsmoduleAppRailsLoaderRUBY=Gem.rubyEXECUTABLES=['bin/rails','script/rails']...defself.exec_app_railsoriginal_cwd=Dir.pwdloopdoifexe=find_executablecontents=File.read(exe)ifcontents=~/(APP|ENGINE)_PATH/execRUBY,exe,*ARGVbreak# non reachable, hack to be able to stub exec in the test suite
railsコマンドを実行する際にカレントディレクトリをアプリ直下にしていますので、bin/railsファイルが見つかります。ここでは見つけたファイルを読み込んで、Rubyのスクリプトとして実行しています。
bin/rails
bin/rails
# !/usr/bin/env rubyAPP_PATH=File.expand_path('../../config/application',__FILE__)require_relative'../config/boot'require'rails/commands'
bin/railsでは、アプリとGemfileの設定を準備してから、フレームワークのcommands.rbをロードしています。
railties-4.1.1/lib
commands.rbを確認してみます。
引数が無ければヘルプ表示、各コマンドの省略形の対応を行った後でコマンドを実行するようです。
rails/commands.rb
ARGV<<'--help'ifARGV.empty?aliases={"g"=>"generate","d"=>"destroy","c"=>"console","s"=>"server","db"=>"dbconsole","r"=>"runner"}command=ARGV.shiftcommand=aliases[command]||commandrequire'rails/commands/commands_tasks'Rails::CommandsTasks.new(ARGV).run_command!(command)
rails/commands/commands_tasks.rb
moduleRails...classCommandsTasks# :nodoc:...defrun_command!(command)command=parse_command(command)ifCOMMAND_WHITELIST.include?(command)send(command)elsewrite_error_message(command)endend
consoleメソッドではrequire_commandを用いて、コマンドと同名のファイルを読み込んで実行しています。
rails/commands/commands_tasks.rb
...defconsolerequire_command!("console")options=Rails::Console.parse_arguments(argv)# RAILS_ENV needs to be set before config/application is requiredENV['RAILS_ENV']=options[:environment]ifoptions[:environment]# shift ARGV so IRB doesn't freakshift_argv!require_application_and_environment!Rails::Console.start(Rails.application,options)end...private...defrequire_command!(command)require"rails/commands/#{command}"end
commands
提供されるコマンドは次のようになります(commands_tasks.rbを除く):
$tree rails/commandsrails/commands├── application.rb├── commands_tasks.rb├── console.rb├── dbconsole.rb├── destroy.rb├── generate.rb├── plugin.rb├── runner.rb├── server.rb└── update.rb0 directories, 10 files
console
rails/commands/console.rb
moduleRailsclassConsoleclass<<selfdefstart(*args)new(*args).startend...definitialize(app,options={})@app=app@options=optionsapp.sandbox=sandbox?app.load_console@console=app.config.console||IRBend...defstart...ifdefined?(console::ExtendCommandBundle)console::ExtendCommandBundle.send:include,Rails::ConsoleMethodsendconsole.startend
ConsoleMethodsで検索すると・・・app.rbとhelpers.rbで定義されているようです。
$ack ConsoleMethodsrails/console/app.rb5: module ConsoleMethodsrails/console/helpers.rb2: module ConsoleMethods
app.rbは次のようになります:
rails/console/app.rb
require'active_support/all'require'action_controller'moduleRailsmoduleConsoleMethods# reference the global "app" instance, created on demand. To recreate the# instance, pass a non-false value as the parameter.defapp(create=false)@app_integration_instance=nilifcreate@app_integration_instance||=new_sessiondo|sess|sess.host!"www.example.com"endend# create a new session. If a block is given, the new session will be yielded# to the block before being returned.defnew_sessionapp=Rails.applicationsession=ActionDispatch::Integration::Session.new(app)yieldsessionifblock_given?sessionend# reloads the environmentdefreload!(print=true)puts"Reloading..."ifprintActionDispatch::Reloader.cleanup!ActionDispatch::Reloader.prepare!trueendendend
シンプルなコードですね。(reload!
はここにいたのか!)
IRB
$railscLoadingdevelopmentenvironment(Rails4.1.1)001>app.root_url=>"http://www.example.com/"
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme