Rails チュートリアル 1章 勉強メモ9

Rails チュートリアルの勉強メモ

railstutorial.jp

1章続き rails new 何やってんの?

create_config_files

    271:       def create_config_files
=> 272:         build(:config)
    273:       end

いつもの

     97: def config
 =>  98:   empty_directory "config"
     99: 
    100:   inside "config" do
    101:     template "routes.rb"
    102:     template "application.rb"
    103:     template "environment.rb"
    104:     template "secrets.yml"
    105:     template "cable.yml" unless options[:skip_action_cable]
    106:     template "puma.rb"   unless options[:skip_puma]
    107:     template "spring.rb" if spring_install?
    108: 
    109:     directory "environments"
    110:     directory "initializers"
    111:     directory "locales"
    112:   end
    113: end
  • empty_directory は ディレクトリ作成
  • inside は初めてなので読む
    169: def inside(dir = "", config = {}, &block)
 => 170:   verbose = config.fetch(:verbose, false)
    171:   pretend = options[:pretend]
    172: 
    173:   say_status :inside, dir, verbose
    174:   shell.padding += 1 if verbose
    175:   @destination_stack.push File.expand_path(dir, destination_root)
    176: 
    177:   # If the directory doesnt exist and we're not pretending
    178:   if !File.exist?(destination_root) && !pretend
    179:     require "fileutils"
    180:     FileUtils.mkdir_p(destination_root)
    181:   end
    182: 
    183:   if pretend
    184:     # In pretend mode, just yield down to the block
    185:     block.arity == 1 ? yield(destination_root) : yield
    186:   else
    187:     require "fileutils"
    188:     FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield }
    189:   end
    190: 
    191:   @destination_stack.pop
    192:   shell.padding -= 1 if verbose
    193: end
  • say_status は verbose が true なら詳細が表示されるのだろう
  • @destination_stack に config が push
  • 178: config が作られてなかったら mkdir するってこと?empty_directoryで作ってるんじゃないのか・・・?(pretend は dry_run
  • 188: config に cd して yield
  • template と directory をそれぞれ実行(directory は ディレクトリを作って中身を template

create_boot_file

- rails/generators/rails/app/app_generator.rb @ line 288 Rails::Generators::AppGenerator#create_boot_file:

    287: def create_boot_file
 => 288:   template "config/boot.rb"
    289: end
  • config/boot.rb を生成

create_active_record_files

- rails/generators/rails/app/app_generator.rb @ line 292 Rails::Generators::AppGenerator#create_active_record_files:

    291: def create_active_record_files
 => 292:   return if options[:skip_active_record]
    293:   build(:database_yml)
    294: end
  • skip_active_record なら skip
- rails/generators/rails/app/app_generator.rb @ line 155 Rails::AppBuilder#database_yml:

    154: def database_yml
 => 155:   template "config/databases/#{options[:database]}.yml", "config/database.yml"
    156: end
  • options[:database] は設定しているデータベース(例: "database"=>"sqlite3"

create_db_files

- rails/generators/rails/app/app_generator.rb @ line 297 Rails::Generators::AppGenerator#create_db_files:

    296: def create_db_files
 => 297:   return if options[:skip_active_record]
    298:   build(:db)
    299: end
- rails/generators/rails/app/app_generator.rb @ line 159 Rails::AppBuilder#db:

    158: def db
 => 159:   directory "db"
    160: end

create_lib_files

- rails/app/app_generator.rb @ line 302 Rails::Generators::AppGenerator#create_lib_files:

    301: def create_lib_files
 => 302:   build(:lib)
    303: end
- rails/app/app_generator.rb @ line 163 Rails::AppBuilder#lib:

    162: def lib
 => 163:   empty_directory "lib"
    164:   empty_directory_with_keep_file "lib/tasks"
    165:   empty_directory_with_keep_file "lib/assets"
    166: end
  • lib 以下を生成

create_log_files, create_public_files, create_test_files, create_system_test_files, create_tmp_files, create_vendor_files

    def log
      empty_directory_with_keep_file "log"
    end

    def public_directory
      directory "public", "public", recursive: false
    end

    def test
      empty_directory_with_keep_file "test/fixtures"
      empty_directory_with_keep_file "test/fixtures/files"
      empty_directory_with_keep_file "test/controllers"
      empty_directory_with_keep_file "test/mailers"
      empty_directory_with_keep_file "test/models"
      empty_directory_with_keep_file "test/helpers"
      empty_directory_with_keep_file "test/integration"

      template "test/test_helper.rb"
    end

    def system_test
      empty_directory_with_keep_file "test/system"

      template "test/application_system_test_case.rb"
    end

    def tmp
      empty_directory_with_keep_file "tmp"
      empty_directory "tmp/cache"
      empty_directory "tmp/cache/assets"
    end

    def vendor
      empty_directory_with_keep_file "vendor"

      unless options[:skip_yarn]
        template "package.json"
      end
    end
  • 他も全部同じような感じ
  • skip_yarn なら package.json は skip

delete_app_assets_if_api_option, delete_app_helpers_if_api_option, delete_application_layout_file_if_api_option, delete_public_files_if_api_option

      def delete_app_assets_if_api_option
        if options[:api]
          remove_dir "app/assets"
          remove_dir "lib/assets"
          remove_dir "tmp/cache/assets"
        end
      end

      def delete_app_helpers_if_api_option
        if options[:api]
          remove_dir "app/helpers"
          remove_dir "test/helpers"
        end
      end

      def delete_application_layout_file_if_api_option
        if options[:api]
          remove_file "app/views/layouts/application.html.erb"
        end
      end

      def delete_public_files_if_api_option
        if options[:api]
          remove_file "public/404.html"
          remove_file "public/422.html"
          remove_file "public/500.html"
          remove_file "public/apple-touch-icon-precomposed.png"
          remove_file "public/apple-touch-icon.png"
          remove_file "public/favicon.ico"
        end
      end
  • api オプション true なら remove
  • 今回は api オプションつけてないので全部 skip

残りの delete 系

- delete_js_folder_skipping_javascript
- delete_assets_initializer_skipping_sprockets
- delete_application_record_skipping_active_record
- delete_action_mailer_files_skipping_action_mailer
- delete_action_cable_files_skipping_action_cable
- delete_non_api_initializers_if_api_option
- delete_api_initializers
- delete_new_framework_defaults
- delete_bin_yarn_if_skip_yarn_option
  • 今回は skip true なものはないためほとんど skip
  • delete_api_initializers と delete_new_framework_defaults は api = false だと実行
      def delete_api_initializers
        unless options[:api]
          remove_file "config/initializers/cors.rb"
        end
      end

      def delete_new_framework_defaults
        unless options[:update]
          remove_file "config/initializers/new_framework_defaults_5_1.rb"
        end
      end
  • 内容はどちらも remove_file

finish_template

- rails/app/app_generator.rb @ line 418 Rails::Generators::AppGenerator#finish_template:

    416: def finish_template
    417:   binding.pry
 => 418:   build(:leftovers)
    419: end
  • leftovers, 追えなかった
    • grep しても見つからず・・・
    • 出力も特にないのでわからない

apply_rails_template

- rails/generators/app_base.rb @ line 163 Rails::Generators::AppBase#apply_rails_template:

    161: def apply_rails_template # :doc:
 => 162:   apply rails_template if rails_template
    163: rescue Thor::Error, LoadError, Errno::ENOENT => e
    164:   raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
    165: end

run_bundle

- rails/generators/app_base.rb @ line 417 Rails::Generators::AppBase#run_bundle:

    415: def run_bundle
 => 416:   bundle_command("install") if bundle_install?
    417: end
  • bundle_install? = true なので bundle install を実行

run_webpack

- rails/generators/app_base.rb @ line 421 Rails::Generators::AppBase#run_webpack:

    419: def run_webpack
 => 420:   if !(webpack = options[:webpack]).nil?
    421:     rails_command "webpacker:install"
    422:     rails_command "webpacker:install:#{webpack}" unless webpack == "webpack"
    423:   end
    424: end
  • !(webpack = options[:webpack]).nil? が false なので skip

generate_spring_binstubs

- rails/generators/app_base.rb @ line 428 Rails::Generators::AppBase#generate_spring_binstubs:

    426: def generate_spring_binstubs
 => 427:   if bundle_install? && spring_install?
    428:     bundle_command("exec spring binstub --all")
    429:   end
    430: end
  • bundle exec spring binstub --all を実行

run_after_bundle_callbacks

  • 最後のメソッド
  • これを実行してついに rails new は終わり
rails/app/app_generator.rb @ line 424 Rails::Generators::AppGenerator#run_after_bundle_callbacks:

    423: def run_after_bundle_callbacks
 => 424:   @after_bundle_callbacks.each(&:call)
    425: end
  • &:call は { |after_bundle_callback| after_bundle_callback.call } 的な意らしい?(違ってたら教えてください
  • @after_bundle_callbacks = [] なのでなしってこと?

at_exit

  • ここ以降は exit 処理だと思います
  • 一応追えるとこまで追いましたがよくわからなかった
- concurrent/utility/at_exit.rb @ line 49 Concurrent::AtExitImplementation#install:

           # install `Kernel#at_exit` callback to execute added handlers
    46: def install
    47:   synchronize do
    48:     @installed ||= begin
 => 49:                      at_exit { runner }
    50:                      true
    51:                    end
    52:     self
    53:   end
    54: end
  • concurrent-ruby、並行処理 gem らしい
    • @after_bundle_callbacks.each(&:call) これが並行処理なのかも (each(&:call) だし・・・(違ってたらry
  • ちなみに Thread.list してみたが Thread は最初のスレッドひとつだった
[2] pry(#<Rails::Generators::AppGenerator>)> Thread.list
=> [#<Thread:0x00007ff5f705bfa0 run>]
  • at_exit { runner }

    • 実行しているスレッドにKernel#at_exitcallback を実行するハンドラを入れる?
  • runnner

- concurrent/utility/at_exit.rb @ line 88 Concurrent::AtExitImplementation#runner:

    87: def runner
 => 88:   run if synchronize { @enabled }
    89: end
  • run は [ ]
  • synchronize
- concurrent/synchronization/mutex_lockable_object.rb @ line 38 Concurrent::Synchronization::MutexLockableObject#synchronize:

    37: def synchronize
 => 38:   if @__Lock__.owned?
    39:     yield
    40:   else
    41:     @__Lock__.synchronize { yield }
    42:   end
    43: end
  • mutex 理解してないが 所有権を持っていないらしいので @Lock.synchronize { yield }
  • @enabled は true のため run 実行
  • run
- concurrent/utility/at_exit.rb @ line 69 Concurrent::AtExitImplementation#run:

    68: def run
 => 69:   handlers, _ = synchronize { handlers, @handlers = @handlers, {} }
    70:   handlers.each do |_, handler|
    71:     begin
    72:       handler.call
    73:     rescue => error
    74:       Concurrent.global_logger.call(ERROR, error)
    75:     end
    76:   end
    77:   handlers.keys
    78: end
  • @Lock.synchronize { yield }
    • yield は handlers, @handlers = @handlers, {}
  • { } を返している
  • handlers = {} なので何事もなく終了?ってこと
  • 流石にこのあたりは読めない・・・

rails new まとめ

  • rails new 自体が何をやっているかはわかったが終了処理とかよくわかんなくてグダグダになってしまった
  • 次回は rails チュートリアルに戻ります