🍣

Ruby on Railsのコードが一緒なのに環境によって表示文章が異なる現象と対応

2021/05/02に公開

はじめに

最近タイトルの現象に出会って調査したので、発生条件から対応までを備忘録として残します。

条件

  • ローカル上の開発環境
    • Ruby: 2.3.8
    • Ruby on Rails: 4.2.6
    • コンテナイメージ: ruby:2.3.8
  • クラウド上の開発環境
    • Ruby: 2.3.8
    • Ruby on Rails: 4.2.6
    • コンテナイメージ: alpine:3.10
  • 各localeファイルに同じキーが存在する(以下コードを参照)
en.yml
en:
  hello: "Hello world."
en2.yml
en:
  hello: "Hello another world."
  • localeファイルを読み込むRuby on Railsのコードは、どちらの環境でも同じ

現象

Ruby on Railsでlocaleファイルのキー使用時、各環境で表示文章が異なります。

  • ローカル上の開発環境
    • en2.ymlのキーの値(Hello another world.)を表示する
  • クラウド上の開発環境
    • en.ymlのキーの値(Hello world.)を表示する。

調査

環境ごとで参照しているlocaleファイルが異なっているので、localeファイルの読み込み順番がおかしいのでは考えました。
そのため、Ruby on Rails起動時のlocaleファイル読み込み箇所を調べたところ、config/application.rbで以下のコードにより読み込んでいました。

application.rb
module RailsSample
  class Application < Rails::Application
    # 中略
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.yml')]
  end
end

この読み込み処理(Dir[Rails.root.join('config', 'locales', '**', '*.yml')])をクラウド上の開発環境上でやってみたところ、

app/config/locales/en2.yml
app/config/locales/en.yml

の順で読み込んでいました。

一方、ローカルの開発環境で同様の処理をやってみたところ、

app/config/locales/en.yml
app/config/locales/en2.yml

の順で読み込んでいました。
そのため、ローカル/クラウド上の開発環境で読み込み処理が変わってしまうことにより、タイトルの現象が起きていると思われます。

では、なぜこの読み込み処理が変わるのか?
読み込み処理について調べていたところ、この記事がヒットしました。
この記事でも私と同様の現象に出会っているようでした。
https://qiita.com/devzooiiooz/items/43da78f1c3c5c0552710

この記事と参照記事から、原因をまとめると、

  • Dirによるファイルの取得順番は生成順ではない
  • ファイルの取得順番は物理エントリ順

とのことでした。
この原因をもとに考えると、ローカル/クラウド上の開発環境でlocaleファイルの物理エントリ順が異なっていたために、読み込みが順不同になってしまったと考えられます。

対応

言わずもがなですが、キーが重複していることが問題なので、重複しないキーに変更することで解決できます。

en.yml
en:
  hello: "Hello world."
en2.yml
en:
  hello2: "Hello another world."

おわりに

読み込み順が不定と知ったときはなぜ?と思いましたが、よくよく考えると、ファイルの集合を読み込んでいるだけなので順不同であることに違和感はないなと思いました。
この記事が誰かのお役に立てれば幸いです。

Discussion