Ruby

新しいItemの作成

Items

最新コメント

ActiveRecord::Rollbackで例外を伝播させずにロールバック後の処理を継続する

wakairo @wakairo

Active RecordのTransactionブロック内で例外が投げられた場合、ActiveRecord::Rollback以外の例外はロールバックの後に再度投げられます。

したがって、処理失敗で例外を投げるメソッド(save!等)を使えば、基本的にその例外はロールバックの後Transactionブロックの外へ伝播します。 これをキャッチしなければ、RailsはHTTPのエラーレスポンスをブラウザ等のクライアントに返します。 つまり、「処理に失敗したら、ロールバックして、あとの処理は切り上げて、エラーレスポンスを返す」という挙動は簡単に実装できます。

一方で、「ロールバック後に例外を出さずに処理を継続する」場合には、ActiveRecord::Rollbackを活用できます。 以下は、Transactionの成否でリダイレクト先を変えるコード例です。

completed = false

ActiveRecord::Base.transaction do
  unless obj1.save && obj2.save
    raise ActiveRecord::Rollback
  end
  completed = true
end

if completed
  redirect_to completed_path
else
  redirect_to uncompleted_path
end
0
Raw
https://www.techtips.page/ja/comments/1106

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

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

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

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

SprocketsからPropshaftへの移行に関する注意点

wakairo @wakairo

Propshaftへ移行したらSprockets用の設定は削除可能

config/environments/production.rb にある以下の設定はSprocketsの設定なので、 Propshaftへ移行したら、削除可能です。

config.assets.compile = false

参考情報

https://www.techtips.page/ja/comments/658

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

SprocketsからPropshaftへの移行に関する注意点

wakairo @wakairo

Propshaftは.erbを処理しない

Sprocketsは拡張子が .erb のファイル(例: foo.scss.erb)を処理しますが、Propshaftは処理しません。 そのため、Sprockets で .erb を処理している場合、Propshaftへ移行するには次のいずれかの対応が必要になります。

  • .erb の利用をやめ、プレーンなCSS/SCSSなどに書き換える
  • .erb の処理を、Propshaftに渡す前の前処理として別途組み込む
0
Raw
https://www.techtips.page/ja/comments/1080

SprocketsからPropshaftへの移行に関する注意点

wakairo @wakairo

Propshaftへの移行に際して、tailwindcss-railsまたはdartsass-railsを選ぶのもあり

Propshaftの公式移行手順では、CSS関連の処理が必要な場合の選択肢として cssbundling-rails のみ紹介されていますが、 tailwindcss-rails と dartsass-rails という選択肢もあります。cssbundling-railsのREADMEには、選び方のヒントが掲載されています。

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

SprocketsからPropshaftへの移行に関する注意点

wakairo @wakairo

SprocketsからPropshaftへの移行手順は、 以下のPropshaftの公式手順で基本的には問題ないと思いますが、 この公式手順に記載されていないものを中心に、 移行における注意点をこのTopicで集約できればと思います。

https://github.com/rails/propshaft/blob/main/UPGRADING.md

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

OmniAuthを利用したログインのボタンやリンクではTurboをオフにした方が無難

wakairo @wakairo
最終更新

OmniAuthを利用すると外部サービスの認証情報を用いたログインが可能となりますが、 そのログインのボタンやリンクでは、以下のようにdata: {turbo: false}を付けてTurboをオフにしないと、ログインが機能しない場合があります。

<%= button_to "Login with GitHub", "/auth/github", data: {turbo: false} %>

なお、公式のREADMEにあるRails向けサンプルでもdata: {turbo: false}が用いられています。

また、Rails 7からは、Turboがデフォルト構成に組み込まれ有効になっているため、OmniAuthを利用する際は本件への注意が必要です。

0
Raw
https://www.techtips.page/ja/comments/1077
🔧1

`yield :foo`と`content_for :foo`の使い分け

wakairo @wakairo

動機

Rails 8.0.2でrails newをして生成されたapp/views/layouts/application.html.erbでは、 以下のようにyield :foocontent_for :fooが混在していました。

<html>
  <head>
    <title><%= content_for(:title) || "Sample" %></title>
(中略)
    <%= yield :head %>

content_forのAPIドキュメントによれば yield :foocontent_for :fooの働きが等価となる場合もあるのですが、 このapplication.html.erbの例のように、片方に統一されず両方を利用しているケースがあったので、 yield :foocontent_for :fooの使い分けについて調べる事にしました。

結論

  • 基本的には、yield :fooを使う。ただし、以下の2つのケースではcontent_for :fooを使う。
  • ケース1:ヘルパーメソッドの中では、yieldは利用できないので、content_for :fooを使う。
  • ケース2:ビュー側で設定されているかどうかに応じて挙動を切り替えるコードを短く書くときにはcontent_for :fooを使う。

詳細

yieldはヘルパーメソッドの中では利用できない

content_forのAPIドキュメントに書かれている通り、 content_forは以下の例のようにヘルパーメソッド内で利用可能ですが、yieldは利用できません。

module StorageHelper
  def stored_content
    content_for(:storage) || "Your storage is empty"
  end
end

yieldとcontent_forでは、設定されていないときの戻り値が異なる

ビュー側で以下のように:fooに対して設定が行われていた場合、

<% content_for :foo do %>
  Foo
<% end %>

yield :foocontent_for :fooの戻り値は、この例ではどちらも" Foo\n"であり、同じになります。

しかし、ビュー側で前述のような記述がなく:fooに対して設定が行われていなかった場合、 yield :fooの戻り値が空文字列("")であるのに対し、content_for :fooの戻り値はnilであり、 戻り値が異なります。

設定されていない場合にcontent_for :foonilを戻す性質を利用することで、<title><%= content_for(:title) || "Sample" %></title>のような設定されているかどうかに応じて挙動を切り替えるコードを短く書くことができます。

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

Rais8でPropshaftを使う環境ではapplication.jsでbootstrapをimportする

wakairo @wakairo

Rais8から標準となったPropshaftを使っている場合でのbootstrap-rubygemのインストールについてです。

結論としましては、公式GitHubレポジトリのインストール方法にある「Sprockets」のところより前はPropshaftでも同様に作業を進め、その後はPropshaftの場合は以下の2行をapp/javascript/application.jsに追加すればインストール完了です。

import "@popperjs/core"
import "bootstrap"

なお、Propshaftの場合のインストール作業全体の例は、こちらのページで紹介されています。ご参考まで。

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