🌈

Railsのオープンソースのapplication.rbを読む

2023/05/08に公開

こんにちは!

Discourseのapplication.rbをざっとみて、気になった記述について調べてみました。

https://railsguides.jp/configuring.html

ソースコード

https://github.com/discourse/discourse/blob/main/config/application.rb

Rubyのバージョンが小さい場合プログラムを終了させる。

アプリケーションが正しく動作するために、Rubyのバージョンが3.2.0以上である必要があり、3.2.0未満の場合はexitで終了させています。そして、このコードはrequire 'rails/all’より上にあるコードなので、Rails自体が読み込まれる前に実行されます。

if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2.0")
  STDERR.puts "Discourse requires Ruby 3.2 or above"
  exit 1
end

Gem::Version.new は文字列のバージョンを比較するためのクラスです。

String#<=>だと1.10の方がバージョンが大きいと出力されてしまうが、Gem::Version.new はRubyGemsのバージョン表記に則って比較できます。

p "1.9"< "1.10" # => false
p Gem::Version.new("1.9")< Gem::Version.new("1.10") # => true

versions = %w[ 1.1  1.10  1.9  1.1.beta9  1.1.beta10 ]
p versions.sort_by{ |v| Gem::Version.new(v) }
# => ["1.1.beta9", "1.1.beta10", "1.1", "1.9", "1.10"]

exitはSystemExitを発生させ、プログラムを終了させます。

デフォルトは0の正常終了。

def hoge
  puts "最初の出力"
  exit
  puts "exit後の出力"
rescue SystemExit => e
  puts "エラーを出力: #{e.inspect}"
end

puts hoge
# => 最初の出力
# => エラーを出力: #<SystemExit: exit>

config/boot.rbの読み込み

そして、その他Railsの主要ライブラリを読み込んでいます

require File.expand_path("../boot", __FILE__)
require "active_record/railtie"
require "action_controller/railtie"
require "action_view/railtie"
require "action_mailer/railtie"
require "sprockets/railtie"

boot.rbには初期値として主に以下の内容が記載されています。

これはGemfileを環境変数に入れ、それが存在した場合、bundler/setuprequireしています。

ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)

require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])

Rubyのバージョン警告

開発環境で推奨バージョン以上のRubyが必要であることを確認しています。つまり、開発者が古いバージョンのRubyを使用している場合、警告メッセージが表示され、推奨バージョンへのアップグレードを促しています。

if !Rails.env.production?
  recommended = File.read(".ruby-version.sample").strip
  if Gem::Version.new(RUBY_VERSION) < Gem::Version.new(recommended)
    STDERR.puts "[Warning] Discourse recommends developing using Ruby v#{recommended} or above. You are using v#{RUBY_VERSION}."
  end
end

strip は文字列の前後にある空白を取り除きます。

p "  abc   ".strip          #=> "abc"

ネストしたファイルの抽出

Dir.globは、あるパターンにマッチするファイルやディレクトリを文字列の配列として展開できます。そして、File.dirname(__FILE__)で現在実行しているファイルのディレクトリを取得して、File.joinでそれらパスの名前を連結させています。

Dir.glob(File.join(File.dirname(__FILE__), "../plugins", "*", "register_provider.rb")) do |p|
  require p
end

環境に応じてGemを読み込む設定

本番環境で「開発、テスト、プロファイル」のグループに属するGemを読み込まないようにしています。

if defined?(Bundler)
  bundler_groups = [:default]

  if !Rails.env.production?
    bundler_groups = bundler_groups.concat(Rails.groups(assets: %w[development test profile]))
  end

  Bundler.require(*bundler_groups)
end

defined? 式 は式があればそれを識別する値を返し、なければ偽を返します

hoge = "hoge"
defined? hoge #=> "local-variable"

def Foo(a,b)
end
p defined? Foo() #=> "method

スキップ設定

開発やテストの段階で不必要なdbやredisの設定を環境変数でスキップしています

if ENV["SKIP_DB_AND_REDIS"] == "1"
  GlobalSetting.skip_db = true
  GlobalSetting.skip_redis = true
end

PBKDF2の設定(パスワードのハッシュ化)

PBKDF2のアルゴリズムの設定です。

config.pbkdf2_iterations = 600_000
config.pbkdf2_algorithm = "sha256"

PBKDF2とは

PBKDF2(Password-Based Key Derivation Function 2)は、パスワードベースの鍵導出関数の一種で、安全なパスワードストレージや鍵導出のために使用されます。PBKDF2は、一般的にハッシュ関数や暗号アルゴリズム(SHA-1、SHA-256など)を利用して、パスワードから暗号キーを導出するために設計されています。
by Chat-GPT4

config.pbkdf2_iterations = 600_000 は、PBKDF2で使用される反復回数を設定しています。反復回数を増やすことで、ブルートフォース攻撃や辞書攻撃に対するセキュリティが向上します。ただし、反復回数が増えるとパフォーマンスに影響が出るため、適切なバランスが重要です。

config.pbkdf2_algorithm = "sha256"は、PBKDF2アルゴリズムで使用されるハッシュ関数です。Rails 7.0から、ActiveSupport::Digest のデフォルトのダイジェストクラスが SHA1 から SHA256 に変更されました。

https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#digest-class-for-activesupport-digest-changing-to-sha256

以上になります。

最後まで閲覧いただき、ありがとうございました!

Discussion