Railsソース学習(一)


ルビーは不思議な言語で、柔軟な文法と驚くべき特性がたくさんあります.Railsという現在異常に流行しているweb開発フレームワークはRuby言語の特性と優位性をよく発揮している.最近Railsでいくつかの小さなプログラムを開発して、その開発効率が本当に高いことを発見して、同時にRuby言語の哲学にも対応しました:楽しいプログラミング.
Railsをよく理解して使うには、ソースコードを読むのが一番です.最近、Railsのソースコードを勉強しています.この過程の心得と出会った問題を記録します.この学習の過程で、私が使用したrubyバージョンは1.8.6で、使用したRailsバージョンは2.3.2です.
Railsを使用する場合、appを作成するのは簡単です.コマンド'rails app_name’はプログラムの基本フレームワークを生成することができる.これは不思議なことですが、どうやってやったのでしょうか.Railsコマンドの実行手順を先に見て、Rubyインストールディレクトリのbinフォルダの下でこの文の中で{RUBY_HOME}を使ってRubyのインストールディレクトリを表して、railsコマンドを見ることができて、テキストエディタで開きます:

#!c:/ruby/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'rails' is installed as part of a gem, and
# this file is here to facilitate running it. 
#

require 'rubygems'
version = "> 0"
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
  version = $1
  ARGV.shift
end
gem 'rails', version
load 'rails'

まず、このファイルの内容を説明します.#の冒頭のコメントは多くありません.
1、require‘rubygems’、この言葉はrubygemsをロードする必要があることを示している.rbファイルですが、このファイルはどこにありますか?ここではrequireがファイルをロードするときの検索パスを知る必要があります.rubyにもjava classpathのようなものがあります.$LOADと呼ばれています.PATH、$:に格納され、requireがロードされた後のファイルはこの変数のパスから始まります.コマンドラインウィンドウを開き、ruby-e"puts$:"またはruby-e"puts$LOAD_を入力します.PATH」はあなたのシステムのrubyのloadpathを表示することができます.

C:\Documents and Settings\Administrator>ruby -e "puts $:"
c:/ruby/lib/ruby/site_ruby/1.8
c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt
c:/ruby/lib/ruby/site_ruby
c:/ruby/lib/ruby/1.8
c:/ruby/lib/ruby/1.8/i386-mswin32
.

ではrequire'rubygems'は、上記のいくつかのパスからrubygemsというファイルを検索します.rb,{RUBY_HOME}/lib/ruby/site_ruby/1.8の下にこのファイルがあります.
2、version=">0"です.gemのデフォルトバージョンをロードすることを意味します.
3、このifは、ユーザーがgemを入力したバージョンを受信することができ、入力しない場合は、デフォルトで最新のバージョンをロードします.
4、gem‘rails’,version呼び出しrubygems.rbのメソッドは、バージョン条件を満たすrailsをアクティブにする役割を果たすメソッドを定義します.
{RUBY_HOME}/lib/ruby/site_ruby/1.8/rubygems.rb

def gem(gem_name, *version_requirements) # :doc:
    skip_list = (ENV['GEM_SKIP'] || "").split(/:/)
    raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name
    Gem.activate(gem_name, *version_requirements)
end

gemインストールをロードするために呼び出されたgem_name関連のファイル、この方法の定義もrubygems.rbでは、この方法は少し長いです.前はversionをチェックし、後ろはgem_を動的に挿入します.name関連bin_pathから$LOAD_PATHでは、後で使用します.
5、最後の「rails」まで、reqiureの機能と同じです.ただし、railsファイルを毎回再ロードするだけで、この「rails」ファイルも$LOAD_からPATHで検索して、前の点でGemと言いました.activate(gem_name,*version_requirements)この方法は最後にgem_を動的に挿入した.name関連bin_pathから$LOAD_PATHでは、このbin_pathには私たちが探している「rails」が含まれています.railsコマンドを編集できるファイルは次のとおりです.

#!c:/ruby/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'rails' is installed as part of a gem, and
# this file is here to facilitate running it. 
#

require 'rubygems'
version = "> 0"
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
  version = $1
  ARGV.shift
end
gem 'rails', version
puts Gem.bin_path('rails','rails',version) #   rails  bin  [color=red][/color]
load 'rails'

これにより、コマンドラインの下に新しくrailsを入力すると、railsが存在するbinパスが先に印刷されることがわかります.つまりload「rails」が探している位置です.私のパソコンに表示されているのは、c:/ruby/lib/ruby/gems/1.8/gems/rails-2.3.2/bin/railsです.
次に、c:/ruby/lib/ruby/gems/1.8/gems/rails-2.3.2/bin/railsパスのrailsファイルに移動し、テキストエディタで開きます.

require File.dirname(__FILE__) + '/../lib/ruby_version_check'
Signal.trap("INT") { puts; exit }

require File.dirname(__FILE__) + '/../lib/rails/version'
if %w(--version -v).include? ARGV.first
  puts "Rails #{Rails::VERSION::STRING}"
  exit(0)
end

freeze   = ARGV.any? { |option| %w(--freeze -f).include?(option) }

app_path = ARGV.first

require File.dirname(__FILE__) + '/../lib/rails_generator'

require 'rails_generator/scripts/generate'
Rails::Generator::Base.use_application_sources!
Rails::Generator::Scripts::Generate.new.run(ARGV, :generator => 'app')

Dir.chdir(app_path) { `rake rails:freeze:gems`; puts "froze" } if freeze

1、rubyのバージョンチェックを行う
2、信号量については、後のリンクで信号量についての説明がありますが、この場所で何をしているのか分かりません.(
http://www.kuqin.com/rubycndocument/man/built-in-class/module_signal.html )
3、railsのバージョン情報をロードし、次のifはユーザーが入力したコマンドに-vまたは-versionがあればrailsのバージョンを表示します.
4、Freezeはあなたのrailsバージョンを凍結し、railsの自動アップグレードによるrailsアプリケーションの互換性の問題を防止することができます.-fまたは-freezeを入力すると、最後にコマンドを実行します:rake rails:freeze:gems、railsをvenderの下に個別にコピーしますが、railsが起動するときはまずこのディレクトリを見て、もしあればロードして、なければシステムをロードします.
5、次の2つのRails::Generatorの先頭はgeneratorを呼び出す場所で、最初の文はrails-2.3.2librails_を呼び出すgenerator\look_up.rbのuse_application_sources!方法、

# Use application generators (app, ?).
   def use_application_sources!
      reset_sources
      sources << PathSource.new(:builtin,"#{File.dirname(__FILE__)}/generators/applications")
   end

PathSourceを使用してrails-2.3.2librails_にナビゲートGeneratorgeneratorsapplicationsフォルダ、2番目の文はrails-2.3.2librails_を呼び出しますgenerator\scripts.rbのrunメソッド.

# Run the generator script.  Takes an array of unparsed arguments
# and a hash of parsed arguments, takes the generator as an option
# or first remaining argument, and invokes the requested command.
  def run(args = [], runtime_options = {})
     begin
       parse!(args.dup, runtime_options)
       rescue OptionParser::InvalidOption => e
       # Don't cry, script. Generators want what you think is invalid.
     end

     # Generator name is the only required option.
     unless options[:generator]
        usage if args.empty?
        options[:generator] ||= args.shift
     end

     # Look up generator instance and invoke command on it.
     Rails::Generator::Base.instance(options[:generator], args, options).command(options[:command]).invoke!
     rescue => e
       puts e
       puts "  #{e.backtrace.join("
")}
" if options[:backtrace] raise SystemExit end

このrunメソッドでは、ARGVのパラメータを解析してから、対応するgeneratorを検索し、対応するgeneratorのインスタンスを生成します.異なるgeneratorには対応するtemplatesがあります.ここで呼び出されたのはapp_generator.rbは、アプリケーション全体のフレームワークを生成します.
最後に、上記のプロセス全体を整理し、railsコマンドを呼び出し、プログラムフレームワークを生成する大まかなプロセスは次のとおりです.
(1)rubybinrailsコマンドを実行する------(2)ruby,RubyGems,railsのバージョンチェック------(3)gemディレクトリの下のrailsインストールパスのbinディレクトリの下のrailsファイルをロードする------(4)コマンドラインパラメータを解析し、対応するgeneratorを呼び出してアプリケーションフレームワークを生成する
PS:freezeについて:Ruby on Railsは、アプリケーションが使用するRailsと関連するRuby Gemsのバージョンをfreezeに許可します.これにより、サーバにインストールされているRailsバージョンがいくらであっても、アプリケーションは常に指定したバージョンを使用します.アプリケーションがビジネスに使用されているか、安定性に高い要求がある場合は、freezeのrailsが必要です.freeze railsを使用しないと、新しいバージョンのrailsをアップグレードした後、互換性の問題で製品が正常に動作しない可能性があります.しかし、freezeがrailsを持っている場合、railsの自動更新がもたらす便利さを得ることはできません.railsの最新バージョンを常に自分で追跡し、必要に応じて自分でアップグレードしなければなりません.後ろのリンクにはfreezeの詳細があります.(
http://support.tigertech.net/freeze-rails )