rails

Ruby on Rails

新しいTopicの作成

Topics

Rails 8.0からRails 8.1への移行(アップデート、アップグレード)で必要な作業

140 views Post
wakairo @wakairo

基本的にはRailsガイドの手順に従えば良いと思います。

ガイドの手順にもありますが、ぜひbin/rails app:updateコマンドを活用しましょう。

Rails 8.1への移行で対応が必要そうな個別の作業について、以下のコメントでそれぞれ取り上げますので、ご参考になれば幸いです。

0
Raw
https://www.techtips.page/ja/comments/1118
wakairo @wakairo

Rails 8.1におけるconfig.action_dispatch.verbose_redirect_logs

config.action_dispatch.verbose_redirect_logsは、リダイレクトのソース位置を関連するログ行の下にログ出力するかどうかの設定です。

rails newで生成されるconfig/environments/development.rbにおいて、 8.1からは以下のようにこの設定を有効にするコードが追加されました(この変更のPRこの変更のCommit)。

+  # Highlight code that triggered redirect in logs.
+  config.action_dispatch.verbose_redirect_logs = true
+

development環境でデバッグする際に使える情報が増える形になると思いますので、既存アプリでもこの設定を追加しても良いかもしれません。

0
Raw
https://www.techtips.page/ja/comments/1119
wakairo @wakairo

Rails 8.1におけるRails.configuration.action_view.remove_hidden_field_autocomplete

config.action_view.remove_hidden_field_autocompleteは、hiddenフィールドからautocomplete="off"属性を除去するかどうかの設定です。 (この機能のPRこの機能のCommitbin/rails app:updateコマンドが生成する config/initializers/new_framework_defaults_8_1.rbには、 以下のようにこの設定を有効にするコードがあります。

+  # Highlight code that triggered redirect in logs.
+  config.action_dispatch.verbose_redirect_logs = true
+

この機能が導入された背景

この機能は、HTML標準へ より準拠したHTMLをRailsが生成するように追加されました。

具体的には、この機能を有効にしない場合、Railsは以下のようなautocomplete="off"属性を付けたhiddenフィールドを生成していました。

<input type="hidden" name="authenticity_token" value="abc123..." autocomplete="off">

このautocomplete属性付きのhiddenフィールドはHTML標準に沿っておらず、 Nu Html Checkerは 以下のメッセージとともに「エラー」として指摘していました。

An “input” element with a “type” attribute whose value is “hidden” must not have an “autocomplete” attribute whose value is “on” or “off”.

0
Raw
https://www.techtips.page/ja/comments/1120
wakairo @wakairo

Rails 8.1におけるconfig.content_security_policy_nonce_auto

config.content_security_policy_nonce_autoは、 Rails 8.1で追加された「CSPのnonceを自動で追加する機能」を有効にするかどうかの設定です。

rails newで生成されるconfig/initializers/content_security_policy.rbにおいて、 8.1からは以下のようにこの設定のコードが追加されました(この変更のPRこの変更のCommit)。

+#   # Automatically add `nonce` to `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag`
+#   # if the corresponding directives are specified in `content_security_policy_nonce_directives`.
+#   # config.content_security_policy_nonce_auto = true
+#

デフォルトではCSP設定自体がコメントアウトされており、この機能の設定もコメントアウトされています。

Railsガイドでは、CSPについての説明が「Content-Security-Policyヘッダー」の項目にあり、 このnonceを自動で追加する機能の説明が「nonceを追加する」の項目にあります。

0
Raw
https://www.techtips.page/ja/comments/1122

Railsモデルのクラスメソッドはメソッドチェーンでも呼べる ― 注意点とscopeへ整理する方針

374 views Post
wakairo @wakairo

Railsでモデルにクラスメソッドを定義すると、メソッドの内容に関わらず、メソッドチェーン(ActiveRecord::Relation)経由でもそのメソッドを呼び出せます。 これが便利な場合がある一方で、エラーにはならないものの、意味的に不正確なコードが書けてしまったり、気を付けないとバグの温床になったりすることもあります。 特に、リレーションを返す用途のクラスメソッドと、そうでないクラスメソッドが混在している場合に混乱が生じやすくなります。 本記事ではその仕組みと注意点、そして実務上の整理方針を解説します。

モデルのクラスメソッドがActiveRecord::Relation経由でも呼べる仕組み

以下のようにPenクラスにクラスメソッドを定義したとします。

class Pen < ApplicationRecord
  def self.with_color(color)
    if color.present?
      where(color: color)
    else
      all
    end
  end
end

定義したこのメソッドは以下のように呼べます。これはRubyにおける通常のクラスメソッド呼び出しです。

test(dev):000> Pen.with_color("red")
  Pen Load (0.1ms)  SELECT "pens".* FROM "pens" WHERE "pens"."color" = 'red' /* loading for pp */ LIMIT 11 
=>
[#<Pen:0x00007b3619af2060
  id: 1,
  color: "red",
  price: 80,
  created_at: "2026-02-20 05:52:53.460900000 +0000",
  updated_at: "2026-02-20 05:52:53.460900000 +0000">,
 #<Pen:0x00007b361a437f80
  id: 3,
  color: "red",
  price: 150,
  created_at: "2026-02-20 05:53:10.752331000 +0000",
  updated_at: "2026-02-20 05:53:10.752331000 +0000">]

では、メソッドチェーンでの呼び出しはどうなっているでしょうか。

まず、whereなどのスコープメソッドを呼び出した結果は、以下で確認できる通り、 PenクラスではなくPen::ActiveRecord_Relationのインスタンスになります。

test(dev):000> Pen.where(created_at: 1.year.ago..).class
=> Pen::ActiveRecord_Relation

このリレーションインスタンスに対しても、クラスメソッドを以下のように呼び出せます。 つまり、モデルに定義したクラスメソッドは、そのモデルに対応したActiveRecord::Relationクラスのインスタンスからも呼べる仕組みになっているのです。この仕組みが、クラスメソッドをメソッドチェーンから呼べるようにしています。

test(dev):000> Pen.where(created_at: 1.year.ago..).with_color("red").count
  Pen Count (0.5ms)  SELECT COUNT(*) FROM "pens" WHERE "pens"."created_at" >= '2025-02-21 07:00:00.454690' AND "pens"."color" = 'red' 
=> 2

メソッドチェーンで呼べてしまうからこそ、モデルのクラスメソッドは責務と名前を明確にする

with_colorのようにクエリを組み立てるメソッドであれば、メソッドチェーンで呼び出せても違和感がないと思います。 しかし、データベースクエリと関係のないメソッドでもクラスメソッドであれば同様にリレーション経由で呼び出せてしまいます。

その結果、クラスメソッドであれば、その処理内容に関わらず、クエリを組み立てるメソッドを間に挟んだメソッドチェーンにおいて、エラーにならず実行できてしまいます。 具体例を見てみましょう。export_to_csvがクラスメソッドだとすると以下のようにwhereを間に挟んでもエラーにならずに実行できます。

Pen.where(created_at: 1.year.ago..).export_to_csv(1, 2)

ではexport_to_csvメソッドは、countのように「条件に合ったレコードに対する処理をするメソッド」なのでしょうか? それとも、クエリ構築とは関係がない「ユーティリティメソッド」で、このメソッドチェーンで呼び出すコードは何かしらのミスの結果なのでしょうか?

この例から分かるのは、モデルクラスに定義するクラスメソッドの名前はより慎重に付けなくてはならないということです。 名前だけではありません。メソッドの責務についても、クエリ用途であるか否かなど、明確さがあることが望まれます。

そのため、モデルのクラスメソッドの責務と名前に一定の規則性を持たせることも1つのアイデアです。 例えば、「findcreateなど、Active Recordのクエリメソッドで使われる単語から名前が始まる場合は、必ずクエリ関連の責務とする」といったルールが考えられます。

また、名前だけでなくコードドキュメントにおいても、他のメソッド以上に使い方をはっきりと示すことが望まれます。

クエリ構築用クラスメソッドでelse節を省くとメソッドチェーンの途中でエラーを招く

クエリ構築用のクラスメソッドの場合には、条件分岐のelse節を省いてしまうと、メソッドチェーンの途中で予期せぬエラーを引き起こす原因になるという注意点もあります。

以下のように、先ほどのwith_colorメソッドからelse節を削除してみましょう。

class Pen < ApplicationRecord
  def self.with_color(color)
    if color.present?
      where(color: color)
    end
  end
end

引数が有効値のとき(color.present?が真になるとき)はエラーになりませんが、 以下のように引数が空文字列で条件を満たさない場合はNoMethodErrorが発生してしまいます。

test(dev):000> Pen.where(created_at: 1.year.ago..).with_color("").count
(test):0:in '<main>': undefined method 'count' for nil (NoMethodError)

これは、以下のように条件を満たさなかった場合の戻り値がnilになってしまうためです。 nilに対してcountメソッドを呼び出そうとしたため、エラーになったのです。

test(dev):000> Pen.where(created_at: 1.year.ago..).with_color("")
=> nil

クエリ構築用メソッドとしてクラスメソッドを設計するなら、 常にActiveRecord::Relationインスタンス(またはそれに準ずるオブジェクト)を返す設計にしておくことが求められます。

リレーションを返す場合はscopeに統一する

クエリ構築の一環としてリレーションを返すことを意図したメソッドは、 クラスメソッドではなくscopeでの定義に統一するのが有効です。 これは、前述したモデルのクラスメソッドに関する困難さを和らげる、シンプルなアプローチの1つです。

1つのプロジェクト内でクラスメソッドでの定義とscopeでの定義を混在させることは、 前述のクラスメソッドの注意点とscopeの注意点を足し合わせることになり、チーム開発における理解コストを上げてしまいます。 では、混在をやめてどちらに統一するのが良いかと言えば、scopeに統一することが有力な戦略です。以下にその理由を3つ述べます。

理由1: scopeとクラスメソッドでは挙動に違いがある

まず大きな違いは、nilまたはfalseを返したときの挙動です(この点については理由3で詳しく後述します)。 また、レシーバとしてモデル名を書いた際にも明確な挙動の違いが確認できます(下記「参考」を参照)。 これらに限らず、他の挙動の差異が潜んでいる可能性もあります。

このように仕様や挙動に差異がある場合、二通りのやり方が混在していると「片方で問題ない書き方がもう片方でバグになる」という厄介さを抱えることになります。また、両方の仕様・挙動に対する知識が求められるため、コードベースの理解コストも上がってしまいます。

(参考)モデルクラス名を明示的にレシーバとした場合の挙動の違い

クエリ構築を行うscopeとクラスメソッドでは、モデルクラス名を明示的にレシーバとして書いてしまうと、 前の条件を引き継ぐか否かに違いが出てしまいます。

具体的には、まず以下のように、Pen.where(color: color)とだけ記述したscopeとクラスメソッドをそれぞれ定義します。

class Pen < ApplicationRecord
  scope :with_color_s, ->(color) { Pen.where(color: color) }

  def self.with_color_m(color)
    Pen.where(color: color)
  end
end

次に、それぞれを実行してみると、以下のような違いが出ます。

test(dev):000> Pen.where(price: 80).with_color_m("red")
  Pen Load (0.2ms)  SELECT "pens".* FROM "pens" WHERE "pens"."price" = 80 AND "pens"."color" = 'red' /* loading for pp */ LIMIT 11 
=>
[#<Pen:0x00007ad76b175648
  id: 1,
  color: "red",
  price: 80,
  created_at: "2026-02-20 05:52:53.460900000 +0000",
  updated_at: "2026-02-20 05:52:53.460900000 +0000">]
test(dev):000> Pen.where(price: 80).with_color_s("red")
  Pen Load (0.2ms)  SELECT "pens".* FROM "pens" WHERE "pens"."color" = 'red' /* loading for pp */ LIMIT 11 
=>
[#<Pen:0x00007ad76ae02d08
  id: 1,
  color: "red",
  price: 80,
  created_at: "2026-02-20 05:52:53.460900000 +0000",
  updated_at: "2026-02-20 05:52:53.460900000 +0000">,
 #<Pen:0x00007ad76ae02bc8
  id: 3,
  color: "red",
  price: 150,
  created_at: "2026-02-20 05:53:10.752331000 +0000",
  updated_at: "2026-02-20 05:53:10.752331000 +0000">]

クラスメソッドのwith_color_mは前の条件where(price: 80)が適切にマージされているのに対し、 scopeのwith_color_sprice: 80の条件が無視されています(where(color: color)のようにレシーバPenを消せば正しくマージされます)。

なお、この違いの確認には執筆時の最新版であるRails 8.1.2を用いました。

理由2: scopeには「リレーションを返す」という共通認識がある

クラスメソッドは、用途が極めて広い汎用的な仕組みです。そのため、メソッド名だけでは「チェーン可能なクエリメソッドなのか」が判断しづらくなります。

一方、scopeは「クエリを組み立ててActiveRecord::Relationを返すためのもの」という開発者間の共通認識があります。 また、scopeは通常のクラスメソッド定義方法とは異なるため、メソッドチェーンで利用できることも自然に受け入れられます。

以上から、scopeの方が、コードの読み書きに必要な認知的負荷が低いと言えます。

理由3: scopeでは、else節を省いた簡潔な記載が可能

RailsのAPIドキュメントによれば、 nilまたはfalseが返された場合にその時点までに構築済みのクエリ条件(allに相当)を返すというのがscopeの仕様です。

そのため、以下のscope定義にはelse節がありませんが、メソッドチェーンの途中で呼び出されてもエラーを引き起こしません。

class Pen < ApplicationRecord
  scope :with_color, ->(color) do
    if color.present?
      where(color: color)
    end
  end
end

これにより、先ほど述べたクラスメソッドが持つ「nilを返してチェーンが壊れる」問題を回避しつつ、条件付きクエリを簡潔に表現できます。

さらにRubyでは、全く同じ処理を以下の一行に書き直せます。

class Pen < ApplicationRecord
  scope :with_color, ->(color) { where(color: color) if color.present? }
end

このようにscopeを使うことで、意図が明確かつ簡潔なコードを書くことが出来ます。

まとめ

  • クエリ用途ではないクラスメソッドを定義するときには、メソッドチェーンで呼び出されることが不自然であると伝わるように、責務や名前の明確さが重要です。
  • リレーションを返すメソッドをscopeでの定義に統一することで、nil返却エラーを防いだり、コードの読み書きを容易にしたり出来ます。
0
Raw
https://www.techtips.page/ja/comments/1115

RailsのAction MailerとAction Mailboxはmail gemを利用している

621 views Post
wakairo @wakairo

RailsでMailクラスに遭遇したら、それはmail gemのものです。ですので、そのAPI情報などは、Railsの情報源ではなく、以下のようなmail gemの情報源を見ると得られます。

0
Raw
https://www.techtips.page/ja/comments/1109

minitest6にアップデートするとrails testがエラーになる

1619 views Post
wakairo @wakairo

現象

2025/12/18にリリースされたminitest 6.0.0のgemにアップデートしたところ、 bin/rails testの実行で以下のエラーが発生して止まりました。ちなみに、テストが1つも無い状態ではこのエラーは発生しませんでした。

Running 1 tests in a single process (parallelization threshold is 50)
Run options: --seed 32547

# Running:

/x/vendor/bundle/ruby/3.4.0/gems/railties-8.0.4/lib/rails/test_unit/line_filtering.rb:7:in 'run': wrong number of arguments (given 3, expected 1..2) (ArgumentError)
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:467:in 'block (2 levels) in Minitest::Runnable.run_suite'
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:463:in 'Array#each'
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:463:in 'block in Minitest::Runnable.run_suite'
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:505:in 'Minitest::Runnable.on_signal'
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:492:in 'Minitest::Runnable.with_info_handler'
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:462:in 'Minitest::Runnable.run_suite'
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:355:in 'block in Minitest.run_all_suites'
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:355:in 'Array#map'
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:355:in 'Minitest.run_all_suites'
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:310:in 'Minitest.run'
        from /x/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.0/lib/minitest.rb:84:in 'block in Minitest.autorun'

とりあえずの回避策

Gemfileのgroup :testのところに以下の記述を追加してminitestのバージョンを6よりも下に設定したところエラーは出なくなりました。

group :test do
  gem "minitest", "< 6"
0
Raw
https://www.techtips.page/ja/comments/1082
😿3
🔄1
🔧1
takuma_tech Takuma @takuma_tech

1/9にリリースされたRails v8.1.2は、minitest6で問題なさそうです。簡単にテストした分には、正常にテストが走りました。

ちなみにv8.1.1は、minitest6にすると、エラーにはならないものの、テストが全く拾われず0 runs, 0 assertions, 0 failures, 0 errors, 0 skipsになっていました。

0
Raw
https://www.techtips.page/ja/comments/1085
😄2
🔄1
❤️1

rails 7.2からrails 8.0への移行(アップデート、アップグレード)で必要な作業

5572 views Post
wakairo @wakairo

基本的にはRailsガイドの手順に従えば良いと思います。

ガイドの手順にもありますが、ぜひbin/rails app:updateコマンドを活用しましょう。

rails 8.0への移行で対応が必要そうな個別の作業について、以下のコメントでそれぞれ取り上げますので、ご参考になれば幸いです。

0
Raw
https://www.techtips.page/ja/comments/649
😄3
🔧1
💯1
❤️1
wakairo @wakairo

不要であればアイコン画像の削除

bin/rails app:updateコマンドを実行すると以下の2つのアイコン画像ファイルがpublic/に作成されますが、
これら2つのファイルは、rails newで生成される新規railsアプリ用のファイルであるため、既存アプリでは単純に削除してしまい、 従来通りのアイコン画像とアイコン設定(faviconやapple-touch-icon)を用いれば大丈夫です。 (もちろん、既存アプリにおいてアイコン設定が適切に行われている場合の話です。)

  • icon.png
  • icon.svg

より詳細な情報はrails 7.2への移行におけるアイコン画像のコメントをご覧ください。

0
Raw
https://www.techtips.page/ja/comments/650
wakairo @wakairo

Rails 8.0への移行におけるActive Storageのmigration

bin/rails app:updateコマンドを実行すると以下の3つのファイルがdb/migrate/に作成されることがありますが、
Active Storageをまだ使用したことがないアプリケーションでは、 これら3つのファイルは単純に削除してしまっても良いはずです。

  • xxx_add_service_name_to_active_storage_blobs.active_storage.rb
  • xxx_create_active_storage_variant_records.active_storage.rb
  • xxx_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb

詳しくは、「Rails 7.1への移行におけるActive Storageのmigration」のコメントをご覧ください。

0
Raw
https://www.techtips.page/ja/comments/651
wakairo @wakairo

Rails 8.0ではfilter_parametersに:cvvと:cvcが追加された

rails newで生成されるconfig/initializers/filter_parameter_logging.rbにおいて、 Rails 8.0でconfig.filter_parameters:cvv:cvcが追加されました。 この追加に関するプルリクエストはこちらです

セキュリティの観点からは、確かにクレジットカードのCVCとCVVをフィルタすることは適切であるように思いますので、既存アプリにおいても:cvvと:cvcを追加すると良さそうです。

0
Raw
https://www.techtips.page/ja/comments/652
wakairo @wakairo

Rails 8.0におけるdeprecation関連の設定の削除

rails newで生成されるconfig/environments/test.rbと同development.rbにおいて、 7.2以前は以下の設定用コードが存在していましたが、 このプルリクエストのマージによって削除されました。

  # Raise exceptions for disallowed deprecations.
  config.active_support.disallowed_deprecation = :raise

  # Tell Active Support which deprecation messages to disallow.
  config.active_support.disallowed_deprecation_warnings = []

削除された理由は、当該プルリクエストによると、アプリが新規生成された直後は非推奨の問題と無縁であるということからのようです。 ですので、非推奨の問題が出てくる可能性のある既存アプリにおいては適切な設定をしたままにしておくのが良さそうです。

1
Raw
https://www.techtips.page/ja/comments/653
🔧1
😿1
wakairo @wakairo

Rails 8.0におけるpublic_file_server.headersの設定の変更

rails newで生成されるconfig/environments/test.rbと同development.rbにおいて、 このプルリクエストのマージによって、 config.public_file_server.headersのキーが以下のように小文字になりました。

-    config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{2.days.to_i}" }
+    config.public_file_server.headers = { "cache-control" => "public, max-age=#{2.days.to_i}" }

変更された理由はRack 3への対応のためですので、既存アプリでも設定を変更するのが良さそうです。

0
Raw
https://www.techtips.page/ja/comments/654
wakairo @wakairo

Rails 8.0におけるquery_log_tags_enabled

config.active_record.query_log_tags_enabledは、SQLクエリのログに実行時情報のコメントを付加する機能を有効にするかどうかの設定です。

rails newで生成されるconfig/environments/development.rbにおいて、 8.0からは以下のようにこの設定が有効になるコードになりました(この変更のPR)。 ちなみに、default値は7.2から変わらずfalseですので、 development.rb内の当該設定を意図的に変更しなければ、既存アプリの挙動が勝手に変わることはありません。

  # Append comments with runtime information tags to SQL queries in logs.
  config.active_record.query_log_tags_enabled = true

確かにdevelopment環境において便利そうな機能ですので、8.0へのアップデートを機に、有効にしても良いかもしれません。

1
Raw
https://www.techtips.page/ja/comments/655
wakairo @wakairo

Rails 8.0におけるassets.quiet

config.assets.quietは、アセット関連リクエストのログ出力を無効にするかどうかの設定です。後述のように、Rails 8.0.0でtrueにする以下の設定が削除されましたが、復活させるPRが出ていますので、既存アプリで削除するかには慎重な判断が必要かもしれません。

  # Suppress logger output for asset requests.
  config.assets.quiet = true

rails newで生成されるconfig/environments/development.rbにおいて、 8.0.0と8.0.1ではこの設定が削除されています(この変更のPR)。 しかし、この設定を削除するとターミナル出力がとっちらかるので設定を復活させるというPRがマージ済みですので、今後のバージョンでは設定が復活します。

0
Raw
https://www.techtips.page/ja/comments/656
wakairo @wakairo
最終更新

Rails 8.0におけるaction_controller.perform_cachingとaction_mailer.perform_caching

config.action_controller.perform_cachingconfig.action_mailer.perform_cachingは、両方ともキャッシュ機能を有効にするかどうかの設定です。

rails newで生成されるconfig/environments/test.rbにおいて、 8.0からは以下のようにこれらの設定を無効にするコードが削除されました(この変更のPRこの変更のCommit)。

-  # Show full error reports and disable caching.
+  # Show full error reports.
   config.consider_all_requests_local = true
-  config.action_controller.perform_caching = false
   config.cache_store = :null_store
-  # Disable caching for Action Mailer templates even if Action Controller
-  # caching is enabled.
-  config.action_mailer.perform_caching = false

公式として8.0からはテスト環境ではキャッシュが効いた状態を標準とするということだと思いますので、既存アプリでも同じ設定変更、つまり、設定の削除をしても良いかもしれません。

0
Raw
https://www.techtips.page/ja/comments/657
wakairo @wakairo

Rails 8.0におけるassets.compile

config.assets.compileは、動的なSprocketsコンパイルを有効にするかどうかの設定です。

rails newで生成されるconfig/environments/production.rbにおいて、 8.0からは以下のようにこの設定が削除されているのですが(この変更のPRこの変更のCommit)、 これは8.0からrails newで生成されるアプリのアセットパイプラインのデフォルトがPropshaftになったことに起因するものです。

-  # Do not fall back to assets pipeline if a precompiled asset is missed.
-  config.assets.compile = false

ですので既存アプリは、Propshaftへ移行する前はこの設定は削除しない方が良いと思われます。

0
Raw
https://www.techtips.page/ja/comments/658
❤️2
wakairo @wakairo
最終更新

Rails 8.0におけるpublic_file_server.headersとassume_ssl

rails newで生成されるconfig/environments/production.rbにおいて、 8.0からは以下の設定2つが追加されているのですが(この変更のPRこの変更のCommit)、 これは8.0からrails newで生成されるアプリでKamal 2対応が行われていることに起因するものです。

+  # Cache assets for far-future expiry since they are all digest stamped.
+  config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" }
   # Assume all access to the app is happening through a SSL-terminating reverse proxy.
-  # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies.
-  # config.assume_ssl = true
+  config.assume_ssl = true

ですので既存アプリでは、Kamal 2対応をしないのであればこれらの設定の追加はしなくても良いと思われます。

0
Raw
https://www.techtips.page/ja/comments/659
wakairo @wakairo
最終更新

Rails 8.0におけるsilence_healthcheck_path

config.silence_healthcheck_pathは、ログ出力を抑制すべきヘルスチェックのパスを指定する設定です。

rails newで生成されるconfig/environments/production.rbにおいて、 8.0からは以下のようにこの設定を行うコードが追加されました(この変更のPRこの変更のCommit)。

  # Prevent health checks from clogging up the logs.
  config.silence_healthcheck_path = "/up"

ヘルスチェックでログが詰まる問題が起きている場合や見やすさなどの理由でヘルスチェックのログを抑制をしたい場合は既存アプリでも同じ設定変更、つまり、設定の追加をしても良いかもしれません。

0
Raw
https://www.techtips.page/ja/comments/660
wakairo @wakairo
最終更新

Rails 8.0におけるaction_mailer.perform_caching

config.action_mailer.perform_cachingは、メーラーテンプレートでフラグメントキャッシングを行うかどうかの設定です。

rails newで生成されるconfig/environments/production.rbにおいて、 8.0からは以下のようにこの設定を行うコードが削除されました(この変更のPRこの変更のCommit)。このキャッシングを無効にするコードの削除により、メーラーテンプレートでのフラグメントキャッシングが有効になります。

-  # Disable caching for Action Mailer templates even if Action Controller
-  # caching is enabled.
-  config.action_mailer.perform_caching = false

既存アプリでもメーラーテンプレートでのフラグメントキャッシングを有効にしたい場合は、このコードの削除により可能です。

0
Raw
https://www.techtips.page/ja/comments/661
wakairo @wakairo

Rails 8.0におけるactive_record.attributes_for_inspect

config.active_record.attributes_for_inspectは、Active Recordオブジェクトのinspectに関わる設定です。

rails newで生成されるconfig/environments/production.rbにおいて、 8.0からこの設定を行う以下のコードが追加されました(この変更のPR)。このコードの追加により、production環境ではinspectの結果に基本的にidのみが含まれるようになります。

  # Only use :id for inspections in production.
  config.active_record.attributes_for_inspect = [ :id ]

この設定はproduction環境でのパフォーマンスの悪化をさけるための変更に端を発していますので、既存アプリでもこのコードを追加すると良いかもしれません。

0
Raw
https://www.techtips.page/ja/comments/662
wakairo @wakairo

Rails 8.0におけるlogger

config.loggerは、Railsアプリで用いるロガーの設定です。

rails newで生成されるconfig/environments/production.rbにおいて、 8.0からこの設定について以下の変更が行われました(この変更のPRその1PRその2)。この変更により、Kamralを用いたproduction環境ではタイムスタンプが二重に表示されなくなります。

-  # Log to STDOUT by default
-  config.logger = ActiveSupport::Logger.new(STDOUT)
-    .tap  { |logger| logger.formatter = Logger::Formatter.new }
-    .then { |logger| ActiveSupport::TaggedLogging.new(logger) }
-
-  # Prepend all log lines with the following tags.
+  # Log to STDOUT with the current request id as a default log tag.
   config.log_tags = [ :request_id ]
+  config.logger   = ActiveSupport::TaggedLogging.logger(STDOUT)

既存アプリでも、production環境でタイムスタンプが二重になっている場合には、この変更を行ってタイムスタンプが1つになるようにすると良いかもしれません。

0
Raw
https://www.techtips.page/ja/comments/663
❤️3

rails 7.2で追加されたGitHubワークフローの設定ファイルci.ymlの内容について

3782 views Post
wakairo @wakairo

rails 7.2では、新規アプリに対してデフォルトでGitHubワークフローの設定ファイルであるci.ymlが生成されるようになりました。そこで、このci.ymlの内容について簡単に解説します。

なお、ci.ymlの最新のテンプレートはこちらでご覧になれます

scan_ruby

bin/brakemanコマンドを実行するジョブです。 Railsの一般的なセキュリティ脆弱性がないかどうかチェックします。

scan_js

bin/importmap auditコマンドを実行するジョブです。 利用しているJavaScriptパッケージにセキュリティ上の脆弱性がないかどうかチェックします。

lint

bin/rubocopコマンドを実行するジョブです。 Rubyの静的コード解析を行い設定されているルールに準拠しているかどうかチェックします。

test

bin/rails testコマンドを実行するジョブです。なお、skip_system_testオプションが無効であれば、システムテストも実行します。

0
Raw
https://www.techtips.page/ja/comments/647

既存のRailsアプリへのDev Containerの導入

3680 views Post
wakairo @wakairo

Rails 7.2においてDev Container設定を生成する機能が追加されました。 例えば既存アプリでは、以下のコマンドで既存アプリ用のDev Container設定を生成できるようになりました。

rails devcontainer

生成した設定は、Visual Studio Codeで利用でき、Dev Containerを利用した既存アプリの開発が可能となります。 必要となるソフトウェアのインストール等、Dev Containerでの開発を開始するための手順についてはDev Containerでの開発ガイドが参考になります。

なお、Visual Studio Code以外のエディタでもDev Containerで開発できるようにするべくDev Container CLIというツールの開発が進んでいますが、2024年12月現在では、ポートフォワーディングに対応していないなど、今のところはまだまだ開発途中のツールであり、実開発に投入するにはまだ早い段階である印象です。

0
Raw
https://www.techtips.page/ja/comments/646

既存のRailsアプリへのRuboCopの導入

4128 views Post
wakairo @wakairo
最終更新

Rails 7.2からRuboCopが新規アプリケーションでデフォルトで有効になりました。 このTopicでは、7.1以前で作成した既存RailsアプリにRuboCopを後から導入して、RuboCopに関して7.2の新規アプリ相当の状態にセットアップする方法をご紹介します。

RuboCop (Omakase Ruby styling for Rails) のインストール

基本的にはrubocop-rails-omakaseの公式ドキュメントのインストール手順に従います。

まず以下のように、Gemfileのgroup :development, :testのところにrubocop-rails-omakaseを追加します。

group :development, :test do

  # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/]
  gem "rubocop-rails-omakase", require: false

end

次にbundle installを実行して、RuboCop等をインストールします。

bundle install

さらに、必須ではありませんが、bin/rubocopでRuboCopを実行できるように、以下のコマンドを実行します。

bundle binstubs rubocop

最後に.rubocop.ymlという名前でファイルを作成し、以下の内容を記述します。

# Omakase Ruby styling for Rails
inherit_gem:
  rubocop-rails-omakase: rubocop.yml

以上でRuboCop (Omakase Ruby styling for Rails) のセットアップが出来ました。

ローカル環境でのbin/rubocopの実行とその結果に対する対応の進め方

以下のコマンドでbin/rubocopを実行でき、omakaseのチェックを行えます。

bin/rubocop

このチェックでの指摘事項が多かった場合、以下のオプションを付けて実行することで、 無視設定を記述した.rubocop_todo.ymlというファイルが作成され、 .rubocop.ymlにもこの無視ファイルを参照する設定が追加されますので、 とりあえず全ての指摘事項を無視するように設定が出来ます。

bin/rubocop --auto-gen-config

設定が出来たら、bin/rubocopを実行して、とりあえず指摘事項の数が0となることを確認します。

1つずつ指摘事項へ対応

ここから先は、以下の手順を繰り返します。

1項目ずつ対応を進め、.rubocop_todo.ymlの中身が無くなったら、.rubocop_todo.ymlを削除すると共に、.rubocop.yml内で.rubocop_todo.ymlを参照している設定を削除します。ここまで終わればRuboCopの諸規則への対応は完了となります。お疲れ様でした。

GitHubワークフロー(CI)でのrubocopの実行

.github/workflows/ci.ymlに相当するファイルがなければ作成します。 この.ymlファイルを編集して、以下のようにjobsの下にlintジョブを追加します。

注意点
jobs:
  lint:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: .ruby-version
          bundler-cache: true

      - name: Lint code for consistent style
        run: bin/rubocop -f github

公式情報

0
Raw
https://www.techtips.page/ja/comments/545
😄2
🔧1
💯1
❤️1

既存のRailsアプリでのDependabotへの対応

4204 views Post
wakairo @wakairo
最終更新

Rails 7.2から新規アプリケーションにおいてDependabotがデフォルトで有効になりました。 具体的には、rails newで生成される新規アプリにおいて、Dependabotの設定ファイルである.github/dependabot.ymlが生成されるようになりました。

Dependabotとは

Dependabotとは、GitHubのサービスであり、リポジトリで使用しているソフトウェアを最新の状態に保つことをサポートしてくれるサービスです。 具体的なDependabotの機能としては、以下の3つがあります

  • Dependabot alerts — リポジトリで使っている依存関係に内在する脆弱性について通知します。
  • Dependabot security updates — 使っている依存関係のうち、既知のセキュリティ脆弱性があるものを更新するための pull request を自動的に生成します。
  • Dependabot version updates — 依存関係を最新に保つための pull request を自動的に発行します。

Dependabotの詳細な理解にはクイックスタート ガイドなどをご利用ください。

既存のRailsアプリでのDependabotへの対応方法

脆弱性の通知機能(Dependabot alerts)は、GitHubのWebページから設定を変更するだけで利用できます

脆弱性に関するpull requestの自動生成機能(Dependabot security updates)も、GitHubのWebページから設定を変更するだけで利用できますが、詳細な設定が必要な場合はdependabot.ymlを通して行います

脆弱性対応以外も含めて最新の状態にするためのpull requestを自動生成する機能(Dependabot version updates)は、dependabot.ymlを通した設定が必要です

(参考)デフォルトのdependabot.ymlの内容

このリンク先で閲覧できるrails newで生成される新規アプリのdependabot.ymlの設定内容は、既存アプリでも参考になるかもしれません。 このdependabot.ymlには、Rails 7.2の時点では、railsアプリで利用しているgemとGitHub Actions(GitHubのCI)で利用しているアクションを最新に保つための設定が記述されています。

0
Raw
https://www.techtips.page/ja/comments/447
😄3
🔄1
🔧1
💡1
💯1

既存のRailsアプリへのBrakemanの導入

4607 views Post
wakairo @wakairo
最終更新

Rails 7.2から新規アプリケーションにおいてBrakemanがデフォルトで有効になりました。 このTopicでは、7.1以前で作成した既存RailsアプリにBrakemanを後から導入して、Brakemanに関して7.2の新規アプリ相当の状態にセットアップする方法をご紹介します。

Brakemanのインストール

まず以下のように、Gemfileのgroup :development, :testのところにbrakemanを追加します。

group :development, :test do

  # Static analysis for security vulnerabilities [https://brakemanscanner.org/]
  gem "brakeman", require: false

end

次にbundle installを実行します。

bundle install

以上でBrakemanのインストールが出来ました。

さらに、必須ではありませんが、bin/brakemanでBrakemanを実行できるように、以下のコマンドを実行します。

bundle binstubs brakeman

ローカル環境でのBrakemanの実行

以下のコマンドでBrakemanを実行でき、デフォルトのチェックを行えます。

bin/brakeman

全てのチェックを実行する場合には、以下のオプション付けて実行します。

bin/brakeman -A

警告の無視に関する設定と管理を行う場合は、以下のオプション付けて実行します。

bin/brakeman -I

以下のように、これら2つのオプションを同時に指定して実行することも出来ます。

bin/brakeman -IA

なお、Brakemanの詳細については公式ドキュメントをご覧ください。 また、brakemanコマンドのオプションについては日本語訳もあります。

GitHubワークフロー(CI)でのBrakemanの実行

.github/workflows/ci.ymlに相当するファイルがなければ作成します。 この.ymlファイルを編集して、以下のようにjobsの下にscan_rubyジョブを追加します。

ymlファイルの設定に関する注意点
  • timeout-minutes:の設定は、実行時間に対して十分余裕を持たせて下さい。
  • ruby-version: .ruby-version」という設定は、プロジェクトルートにある.ruby-versionという名前のファイルで指定されているrubyのバージョンという意味になります。この設定についての詳細はこちらのTopicをご覧下さい。
jobs:
  scan_ruby:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: .ruby-version
          bundler-cache: true

      - name: Scan for common Rails security vulnerabilities using static analysis
        run: bin/brakeman --no-pager
0
Raw
https://www.techtips.page/ja/comments/418
🔧3
😄2
💡1
💯1
❤️1
wakairo @wakairo

bundle binstubs brakemanを用いるやり方に更新しました。

0
Raw
https://www.techtips.page/ja/comments/648