美文网首页
当你输入了rails server之后1

当你输入了rails server之后1

作者: will2yang | 来源:发表于2019-11-05 20:22 被阅读0次

    该部分我们主要把流程梳理到执行 ruby bin/rails server 的命令

    1.首先我们执行which rails命令查看我们调用的是哪个脚本文件,因为我使用的是rbenv的环境所以我会使用 rbenv which rails

    # 这是我在ubuntu上没有装rbenv的情况下的输出
    $ which rails # /usr/local/bin/rails
    
    # 我的mac装了rbenv所以会找到的rails脚本是经过rbenv处理的
    $ which rails # /Users/will/.rbenv/shims/rails
    # 所以要使用  rbenv的which命令 就能找到真正想要的结果
    $ rbenv which rails # /Users/will/.rbenv/versions/2.4.4/bin/rails
    

    接下来我们就看一下这个入口文件有什么

    $ cat /Users/will/.rbenv/versions/2.4.4/bin/rails
    

    首先上部分是判断rails命令后面是否指定了版本号,指定了版本号那么就使用指定的版本号.

    #!/Users/will/.rbenv/versions/2.4.4/bin/ruby
    #
    # This file was generated by RubyGems.
    #
    # The application 'railties' is installed as part of a gem, and
    # this file is here to facilitate running it.
    #
    
    require 'rubygems'
    
    version = ">= 0.a"
    
    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
    
    if Gem.respond_to?(:activate_bin_path)
    load Gem.activate_bin_path('railties', 'rails', version)
    else
    gem "railties", version
    load Gem.bin_path("railties", "rails", version)
    end
    

    https://stackoverflow.com/questions/29787336/why-is-force-encodingbinary-used-here

    既然之前的代码都是为了加载railties里exe下的rails脚本那么我们先看下rails脚本里的代码:

    Gem.bin_path("railties", "rails", ">= 0.a")
    # "/Users/will/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/railties-5.2.1/exe/rails"
    
    # /Users/will/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/railties-5.2.1/exe/rails
    #!/usr/bin/env ruby
    # frozen_string_literal: true
    
    git_path = File.expand_path("../../.git", __dir__)
    
    if File.exist?(git_path)
      railties_path = File.expand_path("../lib", __dir__)
      $:.unshift(railties_path)
    end
    require "rails/cli"
    

    git path 可能是为开发rails的程序员准备的,我们不做探索,那么我们看一下 rails/cli 文件里做了什么。

    # rails/cli
    # frozen_string_literal: true
    
    require "rails/app_loader"
    
    # If we are inside a Rails application this method performs an exec and thus
    # the rest of this script is not run.
    Rails::AppLoader.exec_app
    
    require "rails/ruby_version_check"
    Signal.trap("INT") { puts; exit(1) }
    
    require "rails/command"
    
    if ARGV.first == "plugin"
      ARGV.shift
      Rails::Command.invoke :plugin, ARGV
    else
      Rails::Command.invoke :application, ARGV
    end
    

    首先,cli文件require了app_loader, AppLoader.exec_app 主要是为了找到一个 bin/rails这个文件并且执行它,如果当前目录找不到会向上层的文件夹寻找

    # rails/app_loader
    # frozen_string_literal: true
    
    require "pathname"
    require "rails/version"
    
    module Rails
      module AppLoader # :nodoc:
        extend self
    
        RUBY = Gem.ruby
        EXECUTABLES = ["bin/rails", "script/rails"]
        BUNDLER_WARNING = <<EOS
    Beginning in Rails 4, Rails ships with a `rails` binstub at ./bin/rails that
    should be used instead of the Bundler-generated `rails` binstub.
    
    If you are seeing this message, your binstub at ./bin/rails was generated by
    Bundler instead of Rails.
    
    You might need to regenerate your `rails` binstub locally and add it to source
    control:
    
     rails app:update:bin           # Bear in mind this generates other binstubs
                                    # too that you may or may not want (like yarn)
    
    If you already have Rails binstubs in source control, you might be
    inadverently overwriting them during deployment by using bundle install
    with the --binstubs option.
    
    If your application was created prior to Rails 4, here's how to upgrade:
    
      bundle config --delete bin    # Turn off Bundler's stub generator
      rails app:update:bin          # Use the new Rails executables
      git add bin                   # Add bin/ to source control
    
    You may need to remove bin/ from your .gitignore as well.
    
    When you install a gem whose executable you want to use in your app,
    generate it and add it to source control:
    
      bundle binstubs some-gem-name
      git add bin/new-executable
    
    EOS
    
        def exec_app
          original_cwd = Dir.pwd
    
          loop do
            if exe = find_executable
              contents = File.read(exe)
    
              if contents =~ /(APP|ENGINE)_PATH/
                exec RUBY, exe, *ARGV
                break # non reachable, hack to be able to stub exec in the test suite
              elsif exe.end_with?("bin/rails") && contents.include?("This file was generated by Bundler")
                $stderr.puts(BUNDLER_WARNING)
                Object.const_set(:APP_PATH, File.expand_path("config/application", Dir.pwd))
                require File.expand_path("../boot", APP_PATH)
                require "rails/commands"
                break
              end
            end
    
            # If we exhaust the search there is no executable, this could be a
            # call to generate a new application, so restore the original cwd.
            Dir.chdir(original_cwd) && return if Pathname.new(Dir.pwd).root?
    
            # Otherwise keep moving upwards in search of an executable.
            Dir.chdir("..")
          end
        end
    
        def find_executable
          EXECUTABLES.find { |exe| File.file?(exe) }
        end
      end
    end
    

    执行 bin/rails 的命令后cli 之后的代码就不会执行了
    ruby 的exec命令执行完会直接退出脚本

    相关文章

      网友评论

          本文标题:当你输入了rails server之后1

          本文链接:https://www.haomeiwen.com/subject/dnrmqqtx.html