Slide 1

Slide 1 text

Railsサーバ起動の 裏側 前島 真一(@willnet)

Slide 2

Slide 2 text

Shinichi Maeshima ! " # @netwillnet @willnet http://blog.willnet.in Organizer Rails Consultant

Slide 3

Slide 3 text

具体的には何してる人 なの • 技術やシステム設計に関する質問に答える • コードレビュー • 社内勉強会の開催 • ペアプロ • などなど(採用の相談とか技術以外のことも時々やって る)

Slide 4

Slide 4 text

つまり • Railsの知見を会社に提供するおしごと

Slide 5

Slide 5 text

知見のうちの一つを お話します

Slide 6

Slide 6 text

みんな大好き Ruby on Rails • Railsのお作法(レール)に乗ってるだけで、意識せずにべ んり技術を使えていて最高 • 例えばセキュリティ的には • HTMLの自動エスケープ • CSRFチェック用のトークンを自動で追加 • レスポンスヘッダに自動でセキュアになるやつを追加

Slide 7

Slide 7 text

しかし • 魔法のようなプロダクトであるけれど、何も考えずブラッ クボックスとして扱っているとある日死ぬ • 何も考えずに <%= @post.body.html_safe %> などとす ると… •

Slide 8

Slide 8 text

裏側を理解する事が 大事

Slide 9

Slide 9 text

./bin/rails s の裏側

Slide 10

Slide 10 text

bin/rails #!/usr/bin/env ruby begin load File.expand_path('../spring', __FILE__) rescue LoadError => e raise unless e.message.include?('spring') end APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands'

Slide 11

Slide 11 text

config/boot.rb ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile.

Slide 12

Slide 12 text

bundler/setup • Gemfileに書かれているgemへのLOAD_PATHを追加する • この後からgemのrequireができるようになる

Slide 13

Slide 13 text

railties/lib/rails/ commands.rb require "rails/command" aliases = { "g" => "generate", "d" => "destroy", "c" => "console", "s" => "server", "db" => "dbconsole", "r" => "runner", "t" => "test" } command = ARGV.shift command = aliases[command] || command Rails::Command.invoke command, ARGV

Slide 14

Slide 14 text

lib/rails/commands/ server/server_command.rb def perform set_application_directory! Rails::Server.new(server_options).tap do |server| require APP_PATH Dir.chdir(Rails.application.root) server.start end end

Slide 15

Slide 15 text

APP_PATHはbin/railsで 定義してた #!/usr/bin/env ruby begin load File.expand_path('../spring', __FILE__) rescue LoadError => e raise unless e.message.include?('spring') end APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands'

Slide 16

Slide 16 text

config/applicaiton.rb require_relative 'boot' require 'rails/all' Bundler.require(*Rails.groups) module Hikalab class Application < Rails::Application config.load_defaults 5.1 end end

Slide 17

Slide 17 text

railties/lib/rails/ all.rb require "rails" %w( active_record/railtie active_storage/engine action_controller/railtie action_view/railtie action_mailer/railtie active_job/railtie action_cable/engine rails/test_unit/railtie sprockets/railtie ).each do |railtie| begin require railtie rescue LoadError end end

Slide 18

Slide 18 text

railties/lib/rails.rb module Rails class << self @application = @app_class = nil attr_writer :application def application @application ||= (app_class.instance if app_class) end # The Configuration instance used to configure the Rails environment def configuration application.config end def root application && application.config.root end def env @_env ||= ActiveSupport::StringInquirer.new( ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || “development" ) end end end

Slide 19

Slide 19 text

activerecord/lib/ active_record/railtie.rb module ActiveRecord class Railtie < Rails::Railtie initializer "active_record.initialize_timezone" do ActiveSupport.on_load(:active_record) do self.time_zone_aware_attributes = true self.default_timezone = :utc end end initializer "active_record.logger" do ActiveSupport.on_load(:active_record) { self.logger ||= ::Rails.logger } end initializer "active_record.check_schema_cache_dump" do # ... end end end

Slide 20

Slide 20 text

initializer do…end • Railsの初期設定を登録してあとで遅延実行するためのし くみ

Slide 21

Slide 21 text

config/applicaiton.rb require_relative 'boot' require 'rails/all' Bundler.require(*Rails.groups) module Hikalab class Application < Rails::Application config.load_defaults 5.1 end end

Slide 22

Slide 22 text

Bundler.require • Gemfileに書かれたgemをrequireする

Slide 23

Slide 23 text

サーバが立ち上がるとどうなるか • Rack::Serverは慣習的にconfig.ruという設定ファイルを 読んで立ち上がる

Slide 24

Slide 24 text

config.ru require_relative 'config/environment' run Rails.application

Slide 25

Slide 25 text

config/environment.rb require_relative 'application' Rails.application.initialize!

Slide 26

Slide 26 text

Rails.application.initialize! • ↑みたいなやつを実行する • config/initializers/*.rb を実行する initializer "active_record.initialize_timezone" do ActiveSupport.on_load(:active_record) do self.time_zone_aware_attributes = true self.default_timezone = :utc end end

Slide 27

Slide 27 text

時間足りないので 一旦ここまで

Slide 28

Slide 28 text

Railsのブートのまとめ • Gemfileのgemをrequireできるようにする • Railsの設定に必要なものだけ先にロードする(ただし評 価は後) • Gemfileのgemをrequireする • 初期化処理をする

Slide 29

Slide 29 text

これを知っていると どういうときに 嬉しいか

Slide 30

Slide 30 text

ハマリポイントを 回避できる(ことがある) • gemの読み込み順番に起因するエラー • 設定の読み込み順番に起因するエラー • Rackミドルウェアの順番に起因する(ry

Slide 31

Slide 31 text

読み込み順に関連した事例 http://y-yagi.tumblr.com/post/150899354290/rails

Slide 32

Slide 32 text

まとめ

Slide 33

Slide 33 text

この機能べんり! だけではなくて

Slide 34

Slide 34 text

裏側を理解する事が 大事

Slide 35

Slide 35 text

お互い頑張りましょう