rails new 트렌드를 따라가다

15067 단어 RubyRails
컨디션
- ruby 2.1.1p76
- Rails 4.1.1

파일 명령


갑자기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"

if ARGV.first
  str = ARGV.first
  str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
  if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then
    version = $1
    ARGV.shift
  end
end

gem 'railties', version
load Gem.bin_path('railties', 'rails', version)
if 문장 블록 rails _4.1.1_ new 처럼 첫 번째 파라미터에서 버전을 지정하는 경우에 대응합니다.
railties 버전이 지정되지 않은 경우 Gem::LoadError가 끝납니다.
마지막으로, 지정한 버전에서 railties의 rails를 불러옵니다.리퀘어가 아니라 두 번째 이후에도 읽을 수 있도록.
버전을 지정하지 않을 때의 행동을irb로 시도해 보십시오
irb
> gem 'railties', ">= 0"
=> true
> load Gem.bin_path('railties', 'rails', ">= 0")
Usage:
  rails new APP_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 ruby

git_path = File.expand_path('../../../.git', __FILE__)

if File.exist?(git_path)
  railties_path = File.expand_path('../../lib', __FILE__)
  $:.unshift(railties_path)
end
require "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) }

if ARGV.first == 'plugin'
  ARGV.shift
  require 'rails/commands/plugin'
else
  require 'rails/commands/application'
end
Ctrl+C를 누르면 프로그램이 비정상적으로 종료됩니다.rails new의 상황이기 때문에else절에 들어가서 rails/command/application을 불러옵니다.

Generators


계속해서 rails/command/application.확인
rails/commands/application.rb
require 'rails/generators'
require 'rails/generators/rails/app/app_generator'

module Rails
  module Generators
    class AppGenerator # :nodoc:
      # We want to exit on failure to be kind to other libraries
      # This is only when accessing via CLI
      def self.exit_on_failure?
        true
      end
    end
  end
end

args = Rails::Generators::ARGVScrubber.new(ARGV).prepare!
Rails::Generators::AppGenerator.start args
Generator는 Rails3.0Theor 기반에서 시작합니다.
exit_on_failure?중첩, 실패할 때 이상하게 끝납니다.
매개변수를 준비하고 Generator:AppGenerator를 시작합니다.
app_generator.rb의 모양은 다음과 같습니다.
rails/generators/rails/app/app_generator.rb
require 'rails/generators/app_base'

module Rails
  module ActionMethods # :nodoc:
...
  # application builderはapplication generatorの要素を上書きできます。
  #
  # Gemfile、READMEやJavaScriptファイルの作成のなどのように、あなたは全体の操作を上書きでき
  # ます。これらの操作を正確に把握していなくても、別のテンプレートアクションを作成できます。
  class AppBuilder
...
  module Generators
...
    class AppGenerator < AppBase # :nodoc:
...

    # このクラスはAppGeneratorが呼ばれる前に引数を準備します。このクラスはバージョンやヘルプ情
    # 報を求められれば提供し、(追加の設定オプションに用いる)railsrcファイルも構成します。
    # 
    # このクラスはARGVを設定し正しく変化させるため、AppGeneratorの開始前に、このクラスを呼び
    # 出す必要があります。
    class ARGVScrubber # :nodoc
...
      def prepare!
AppBuilder
이 방법으로 응용 프로그램 내의 디렉터리와 복사 파일 등을 만들 수 있다.
AppGenerator
AppBuilder와의 관계가 신경쓰여서 찾아봤는데, getbuilder_class 메서드에서 AppBuilder를 호출합니다.
rails/generators/rails/app/app_generator.rb
  module Generators
...
    class AppGenerator < AppBase # :nodoc:
...
      def get_builder_class
        defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder
      end
이 getbuilder_클라스라는 게 친급 앱베이스야.
rails/generators/app_base.rb
module Rails
  module Generators
    class AppBase < Base # :nodoc:
...
    protected
...
      def builder
        @builder ||= begin
          builder_class = get_builder_class
          builder_class.send(:include, ActionMethods)
          builder_class.new(self)
        end
      end
이러한 관계식은 다음과 같습니다.

Thor: 파생 그룹의 AppGenerator 클래스는 정의된 방법순으로 실행됩니다.
rails/generators/rails/app/app_generator.rb
      def create_root_files
      def create_app_files
      def create_bin_files
      def create_config_files
      def create_boot_file
      def create_active_record_files
      ...
create_root_files 방법 내의build 호출에 주목해 보십시오
rails/generators/rails/app/app_generator.rb
      def create_root_files
        build(:readme)
        ...
build은 AppBase에서 정의하고 builder(AppBuilder)의readme입니다.
rails/generators/app_base.rb
      def build(meth, *args)
        builder.send(meth, *args) if builder.respond_to?(meth)
      end
rails/generators/rails/app/app_generator.rb
  class AppBuilder
...
    def readme
      copy_file "README.rdoc", "README.rdoc"
    end

좋은 웹페이지 즐겨찾기