Rails チュートリアル 1章 勉強メモ3
Rails チュートリアルの勉強メモ
- 今日も生きるために勉強していきましょう
- 前回の続き見ていきます
- いつまで rails new を追ってるんだ
1章続き rails new 何やってんの?
- 前回は
$HOME/.rbenv/versions/*.*.*/bin/rails
を読んだ $HOME/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/railties-5.1.6/exe/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"
短い
$HOME/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/.git
があれば、$HOME/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/railties-5.1.6/lib
の path を追加($:
は path)- その後、"rails/cli" へ
$HOME/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/railties-5.1.6/lib/rails/cli.rb
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
こっちもあんまり長くないなぁ
$HOME/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/railties-5.1.6/lib/rails/app_loader.rb
を読んでいる
require "pathname" require "rails/version" module Rails module AppLoader # :nodoc: extend self RUBY = Gem.ruby EXECUTABLES = ["bin/rails", "script/rails"] BUNDLER_WARNING = <<EOS 略 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
おお、Rails モジュール!ついに出てきました
- require "pathname"
パス名を操作するメソッドが色々あるようだ
require "rails/version"
$HOME/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/railties-5.1.6/lib/rails/version.rb
次はここ
require_relative "gem_version" module Rails # Returns the version of the currently loaded Rails as a string. def self.version VERSION::STRING end end
- 短いからのっける
require_relative
はgem_version
を読み込んでいるrequire
との違いは、require_relative
はこのファイルの位置から指定されたパスのファイルを読み込んでいる
- gem_version.rb も見てみる
module Rails # Returns the version of the currently loaded Rails as a <tt>Gem::Version</tt> def self.gem_version Gem::Version.new VERSION::STRING end module VERSION MAJOR = 5 MINOR = 1 TINY = 6 PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end end
Rails::VERSION::STRING
でバージョンが取れる。面白いversion.rb
でRails.version
で取れるようにしている
Rails.gem_version
で Gem::Version.new してくれるextend self
extend
は 指定したモジュールのメソッドを特異メソッドとして追加する
instance method Object#extend (Ruby 2.6.0)
- ここでは self を渡しているので自分自身のインスタンスメソッドを特異メソッドに追加している
- これをすることでクラスメソッドとして扱える?
- いちいち
self.exec_app
とか書かなくてよくなるって感じだろうか?
- いちいち
- これをすることでクラスメソッドとして扱える?
rails/cli.rb
はrequire "rails/app_loader"
の後早速Rails::AppLoader.exec_app
をしているoriginal_cwd
には元々の rails コマンドを叩いた場所の path が入っているfind_executable
でbin/rails
またはscript/rails
を探している- 見つからなかったら一つ上の Dir へ行くを繰り返す
- rails アプリを new していれば
bin/rails
があるはずなのでおそらくそれを探している - 今回はないのでそのまま続行
- rails アプリを new していれば
rails/ruby_version_check
を呼んでいる。ruby のバージョンをチェックしてそう
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.2.2") && RUBY_ENGINE == "ruby" desc = defined?(RUBY_DESCRIPTION) ? RUBY_DESCRIPTION : "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE})" abort <<-end_message Rails 5 requires Ruby 2.2.2 or newer. You're running #{desc} Please upgrade to Ruby 2.2.2 or newer to continue. end_message end
- ruby のバージョンが 2.2.2 より低ければメッセージを出す
- Signal.trap("INT") { puts; exit(1) }
指定された割り込み signal に対するハンドラとして command を登録します。 指定したシグナルが捕捉された時には例外が発生せず、代わりに command が実行されます。 ブロックを指定した場合にはブロックをハンドラとして登録します。
trap は前回の trap で設定したハンドラを返します。 文字列を登録していた場合はそれを、 ブロックを登録していたらそれを Proc オブジェクトに変換して返します。 また何も登録されていないときも nil を返します。 ruby の仕組みの外でシグナルハンドラが登録された場合 (例えば拡張ライブラリが独自に sigaction を呼んだ場合など) も nil を返します。
- require "rails/command" 次はここを読もうと思ったけど疲れたので一旦終わり