{"id":14877,"date":"2026-09-30T17:30:00","date_gmt":"2026-09-30T12:00:00","guid":{"rendered":"https:\/\/www.allerin.com\/blog\/?p=14877"},"modified":"2026-09-25T11:20:39","modified_gmt":"2026-09-25T05:50:39","slug":"ruby-3-3-to-3-4-upgrade","status":"publish","type":"post","link":"https:\/\/www.allerin.com\/blog\/ruby-3-3-to-3-4-upgrade\/","title":{"rendered":"Ruby 3.3 to 3.4 before your next Rails upgrade"},"content":{"rendered":"<p>Upgrade Ruby 3.3 to 3.4 on your existing Rails version when that combination is tested. Keeping Rails, its defaults and the application\u2019s dependencies fixed makes new failures easier to locate.<\/p>\n<p>If your current framework or a required gem cannot run there, establish a working intermediate combination first. A Ruby requirement such as <code>&gt;= 2.7<\/code> cannot answer that question by itself. Nor does installing the Rails gem prove that its database adapter, debugger or background workers work.<\/p>\n<nav style=\"margin: 24px 0; padding: 18px; background: #edf4f0; border-radius: 6px;\" aria-label=\"Article sections\">\n<p style=\"margin: 0 0 12px;\"><strong>Find the relevant check<\/strong><\/p>\n<ul style=\"display: flex; flex-wrap: wrap; gap: 10px 24px; list-style: none; margin: 0; padding: 0;\">\n<li style=\"margin: 0;\"><a href=\"#choose-the-order-from-evidence\">Choose the order from evidence<\/a><\/li>\n<li style=\"margin: 0;\"><a href=\"#a-library-can-ship-with-ruby-and-still-need-a-gemfile-entry\">A library can ship with Ruby and still need a Gemfile entry<\/a><\/li>\n<li style=\"margin: 0;\"><a href=\"#check-string-mutation-warnings\">Check string mutation warnings<\/a><\/li>\n<li style=\"margin: 0;\"><a href=\"#test-values-instead-of-their-diagnostic-punctuation\">Test values instead of their diagnostic punctuation<\/a><\/li>\n<li style=\"margin: 0;\"><a href=\"#check-the-tools-that-read-or-compile-ruby\">Check the tools that read or compile Ruby<\/a><\/li>\n<li style=\"margin: 0;\"><a href=\"#test-ruby-3-3-to-3-4-with-rails-held-fixed\">Test Ruby 3.3 to 3.4 with Rails held fixed<\/a><\/li>\n<li style=\"margin: 0;\"><a href=\"#what-to-do-this-week\">What to do this week<\/a><\/li>\n<li style=\"margin: 0;\"><a href=\"#ruby-4-0-is-a-separate-next-hop\">Ruby 4.0 is a separate next hop<\/a><\/li>\n<\/ul>\n<\/nav>\n<h2 id=\"choose-the-order-from-evidence\" style=\"scroll-margin-top: 128px;\">Choose the order from evidence<\/h2>\n<p>Checked 7 September 2026, Ruby 3.3 is receiving security fixes, Ruby 3.4 is in normal maintenance, and Ruby 3.2 reached end of life on 1 April 2026. The current patch versions used here are 3.3.12 and 3.4.10. Recheck the <a href=\"https:\/\/www.ruby-lang.org\/en\/downloads\/branches\/\" target=\"_blank\" rel=\"noopener\">Ruby branches<\/a> and <a href=\"https:\/\/www.ruby-lang.org\/en\/downloads\/\" target=\"_blank\" rel=\"noopener\">release list<\/a> when preparing your deployment.<\/p>\n<p>The table combines exact released gemspecs with separately pinned, current non-nightly framework CI selection rules. <strong>S<\/strong> means selected; <strong>A<\/strong> means selected with failures allowed. Neither means a passing build.<\/p>\n<div style=\"overflow-x: auto;\" tabindex=\"0\" role=\"region\" aria-label=\"Rails and Ruby gem requirements and non-nightly CI configuration\">\n<table style=\"width: 100%; min-width: 780px; table-layout: auto; border-collapse: collapse; font-size: 16px; line-height: 1.55;\" aria-label=\"Rails and Ruby gem requirements and non-nightly CI configuration\">\n<thead>\n<tr>\n<th style=\"padding: 14px; border: 1px solid #d3dfdb; background: #edf4f0; text-align: left; vertical-align: top;\" scope=\"col\">Rails tag<\/th>\n<th style=\"padding: 14px; border: 1px solid #d3dfdb; background: #edf4f0; text-align: left; vertical-align: top;\" scope=\"col\">Ruby floor<\/th>\n<th style=\"padding: 14px; border: 1px solid #d3dfdb; background: #edf4f0; text-align: left; vertical-align: top;\" scope=\"col\">3.1<\/th>\n<th style=\"padding: 14px; border: 1px solid #d3dfdb; background: #edf4f0; text-align: left; vertical-align: top;\" scope=\"col\">3.2<\/th>\n<th style=\"padding: 14px; border: 1px solid #d3dfdb; background: #edf4f0; text-align: left; vertical-align: top;\" scope=\"col\">3.3<\/th>\n<th style=\"padding: 14px; border: 1px solid #d3dfdb; background: #edf4f0; text-align: left; vertical-align: top;\" scope=\"col\">3.4<\/th>\n<th style=\"padding: 14px; border: 1px solid #d3dfdb; background: #edf4f0; text-align: left; vertical-align: top;\" scope=\"col\">4.0<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v6.1.7.10\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">6.1.7.10<\/a><\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">2.5<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">A<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">A<\/td>\n<\/tr>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.0.10\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">7.0.10<\/a><\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">2.7<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">A<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">A<\/td>\n<\/tr>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.1.6\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">7.1.6<\/a><\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">2.7<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">A<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">A<\/td>\n<\/tr>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.2.3.2\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">7.2.3.2<\/a><\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">3.1<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">A<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">A<\/td>\n<\/tr>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v8.0.5.1\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">8.0.5.1<\/a><\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">3.2<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Below floor<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<\/tr>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v8.1.3.1\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">8.1.3.1<\/a><\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">3.2<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Below floor<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">S<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>Framework CI lives in another official repository. These <a href=\"https:\/\/github.com\/rails\/buildkite-config\/blob\/85fd52e62c9c0b9b1d5ea4c574bafba5597db030\/pipelines\/rails-ci\/pipeline.rb\" target=\"_blank\" rel=\"noopener\">pipeline<\/a> and <a href=\"https:\/\/github.com\/rails\/buildkite-config\/blob\/85fd52e62c9c0b9b1d5ea4c574bafba5597db030\/lib\/buildkite\/config\/build_context.rb\" target=\"_blank\" rel=\"noopener\">selection rules<\/a> were checked on 7 September; they are not historical CI runs preserved in those release tags.<\/p>\n<p>An absent entry means this evidence does not answer the question. Older Rails branches also retain their own support deadlines, regardless of whether a newer Ruby boots them. Check the <a href=\"https:\/\/www.allerin.com\/services\/ruby-on-rails\/support-calendar\">Rails and Ruby support calendar<\/a> separately.<\/p>\n<p>The practical order is conditional. Test the current Rails patch and locked gems on both Rubies. If they pass, deploy the Ruby change independently. If they cannot, identify the specific blocker and move Rails or that dependency to a verified intermediate combination. Do not choose \u201cthe highest supported Ruby\u201d by interpreting an unbounded gemspec as a compatibility promise.<\/p>\n<h2 id=\"a-library-can-ship-with-ruby-and-still-need-a-gemfile-entry\" style=\"scroll-margin-top: 128px;\">A library can ship with Ruby and still need a Gemfile entry<\/h2>\n<p>Ruby\u2019s standard-library gemification lets libraries receive releases independently of the interpreter. <a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2017\/12\/25\/ruby-2-5-0-released\/\" target=\"_blank\" rel=\"noopener\">Ruby 2.5\u2019s 2017 release<\/a> already documented libraries becoming default gems. The operational distinction is between a default gem, available without a Gemfile declaration, and a bundled gem that Bundler must include in the resolved dependency graph. A transitive dependency can supply it, but an application that uses it directly should declare it.<\/p>\n<p>Ruby 3.4\u2019s December 2024 tagged NEWS lists twelve default-to-bundled promotions, including <code>mutex_m<\/code>, <code>getoptlong<\/code>, <code>base64<\/code>, <code>bigdecimal<\/code>, <code>observer<\/code>, <code>abbrev<\/code>, <code>resolv-replace<\/code>, <code>rinda<\/code>, <code>drb<\/code>, <code>nkf<\/code>, <code>syslog<\/code> and <code>csv<\/code>. It separately adds <code>repl_type_completor<\/code> as a bundled gem. <a href=\"https:\/\/github.com\/ruby\/ruby\/blob\/v3_4_0\/NEWS.md#stdlib-updates\" target=\"_blank\" rel=\"noopener\">Ruby 3.4 library changes<\/a>.<\/p>\n<p>A small Gemfile without these dependencies loads <code>bigdecimal<\/code>, <code>drb<\/code> and <code>mutex_m<\/code> under Ruby 3.3.12, with migration warnings. Ruby 3.4.10 raises <code>LoadError<\/code> for each. One recorded warning is:<\/p>\n<pre style=\"overflow-x: auto; max-width: 100%;\"><code class=\"language-text\">warning: bigdecimal was loaded from the standard library, but will no longer be part of the default gems starting from Ruby 3.4.0.\r\n<\/code><\/pre>\n<p>For that reproduction, the repair is explicit:<\/p>\n<pre style=\"overflow-x: auto; max-width: 100%;\"><code class=\"language-diff\">+gem \"bigdecimal\", \"4.1.2\"\r\n+gem \"drb\", \"2.2.3\"\r\n+gem \"mutex_m\", \"0.3.0\"\r\n<\/code><\/pre>\n<p>Those are the reproduction\u2019s versions, not a prescription to pin every application to them. Add only dependencies your application needs, resolve them against its lockfile, and rerun boot and parallel tests. Rails already repaired several framework dependencies. Active Support 7.1.0\u2019s 2023 release declared <code>bigdecimal<\/code>, <code>drb<\/code>, <code>mutex_m<\/code> and <code>base64<\/code>; Rails 7.0.9 received backports in 2025. Check the actual patch before adding workarounds for an older report. <a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.1.0\/activesupport\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">7.1 changelog<\/a>, <a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.0.9\/activesupport\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">7.0.9 changelog<\/a>.<\/p>\n<p>The logger incident shows why patch precision matters. On 15 January 2025, concurrent-ruby 1.3.5 removed its logger dependency. Rails 7.0.8.7 relied on that load order; an explicit <code>require \"logger\"<\/code> before Active Support addressed that historical failure. Rails 7.0.9 included the explicit require, and Rails 7.1.0 already had it. A blanket instruction to pin concurrent-ruby for every Rails 7.0 application is stale. <a href=\"https:\/\/github.com\/ruby-concurrency\/concurrent-ruby\/blob\/v1.3.5\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">Dependency change<\/a>, <a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.0.9\/activesupport\/lib\/active_support\/logger_thread_safe_level.rb\" target=\"_blank\" rel=\"noopener\">7.0.9 source<\/a>, <a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.1.0\/activesupport\/lib\/active_support\/logger_thread_safe_level.rb\" target=\"_blank\" rel=\"noopener\">7.1.0 source<\/a>.<\/p>\n<h2 id=\"check-string-mutation-warnings\" style=\"scroll-margin-top: 128px;\">Check string mutation warnings<\/h2>\n<p>Ruby 2.3 introduced the <code>frozen_string_literal<\/code> comment in 2015 to allow immutable literals on a file-by-file basis. Ruby 3.4 adds a transition for files without that comment. Their literals remain mutable, but mutation produces a deprecation warning when enabled. <a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2015\/12\/25\/ruby-2-3-0-released\/\" target=\"_blank\" rel=\"noopener\">Ruby 2.3 release<\/a>, <a href=\"https:\/\/bugs.ruby-lang.org\/issues\/20205\" target=\"_blank\" rel=\"noopener\">transition design<\/a>.<\/p>\n<pre style=\"overflow-x: auto; max-width: 100%;\"><code class=\"language-ruby\">message = \"draft\"\r\nmessage &lt;&lt; \" ready\"\r\n<\/code><\/pre>\n<p>Running that file with <code>ruby -W:deprecated<\/code> on 3.4.10 prints:<\/p>\n<pre style=\"overflow-x: auto; max-width: 100%;\"><code class=\"language-text\">warning: literal string will be frozen in the future (run with --debug-frozen-string-literal for more information)\r\n<\/code><\/pre>\n<p>The corresponding test still passes. Running it with <code>--enable-frozen-string-literal<\/code> deliberately changes the condition and raises <code>FrozenError<\/code> on both tested Rubies. Keep that experiment separate from the normal 3.4 job; it is not evidence that every 3.4 upgrade breaks string mutation.<\/p>\n<p>Use <code>+\"draft\"<\/code> or <code>\"draft\".dup<\/code> when constructing a mutable buffer. An explicit <code># frozen_string_literal: false<\/code> opts a file out while its mutation sites are reviewed. Changing the comment to <code>true<\/code> is a deliberate behavior change, not a warning-suppression fix. Ruby 4.0 still documents the default as false; a warning is not a promised switch date. <a href=\"https:\/\/docs.ruby-lang.org\/en\/4.0\/syntax\/comments_rdoc.html#label-frozen_string_literal+Directive\" target=\"_blank\" rel=\"noopener\">Ruby 4.0 string directive<\/a>.<\/p>\n<h2 id=\"test-values-instead-of-their-diagnostic-punctuation\" style=\"scroll-margin-top: 128px;\">Test values instead of their diagnostic punctuation<\/h2>\n<p>Ruby 3.4 changes <code>Hash#inspect<\/code>. The original discussion began with ambiguous output for unusual symbol keys and broadened into a consistent format. <a href=\"https:\/\/bugs.ruby-lang.org\/issues\/20433\" target=\"_blank\" rel=\"noopener\">Design discussion<\/a>. The same data now renders differently:<\/p>\n<pre style=\"overflow-x: auto; max-width: 100%;\"><code class=\"language-diff\">-{:status=&gt;\"queued\", \"attempt\"=&gt;1}\r\n+{status: \"queued\", \"attempt\" =&gt; 1}\r\n<\/code><\/pre>\n<p>A recorded snapshot assertion fails solely because it compares that representation. Compare the hash\u2019s values when those are the contract. When the actual requirement is a log or user-facing message, test the relevant fields or define an explicit serialization format instead of inheriting <code>inspect<\/code> formatting.<\/p>\n<p>Error and backtrace display also changes. A check for <code>undefined method `deliver_now'<\/code> fails when Ruby prints <code>undefined method 'deliver_now'<\/code>; a backtrace gains the class-qualified method name and different quotation marks. The repaired tests assert <code>NoMethodError<\/code>, its <code>name<\/code>, and <code style=\"overflow-wrap: anywhere; white-space: normal;\">backtrace_locations.first.base_label<\/code>. All three output-sensitive tests fail on 3.4 before the repair and pass on both runtimes afterward. <a href=\"https:\/\/bugs.ruby-lang.org\/issues\/16495\" target=\"_blank\" rel=\"noopener\">Quote consistency<\/a>, <a href=\"https:\/\/bugs.ruby-lang.org\/issues\/19117\" target=\"_blank\" rel=\"noopener\">method-owner backtraces<\/a>.<\/p>\n<p>The <code>Hash#inspect<\/code> change does not itself change JSON or YAML serialization. It matters to those files only if application code stored an inspected string inside them. Avoid rewriting unrelated fixtures to accommodate a diagnostic display change.<\/p>\n<h2 id=\"check-the-tools-that-read-or-compile-ruby\" style=\"scroll-margin-top: 128px;\">Check the tools that read or compile Ruby<\/h2>\n<p>Prism became Ruby\u2019s default parser in 3.4. Ruby\u2019s own parser, a linter\u2019s parser and a coverage tool are distinct dependencies; switching the interpreter does not update them all. The compatibility escape hatch <code>ruby --parser=parse.y<\/code> works in the recorded 3.4.10 probe. Use it to isolate a parser issue and report a reproduction, not to avoid checking your tooling. Ruby 3.3 shipped Prism in 2023 alongside the existing parser; 3.4 made it the default. Tools adopting its parsing or translation APIs move on their own release schedules. <a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2023\/12\/25\/ruby-3-3-0-released\/\" target=\"_blank\" rel=\"noopener\">Ruby 3.3 parser introduction<\/a>.<\/p>\n<p>These are verified upstream checkpoints, not universal minimum versions. The fixture does not certify each tool against your application.<\/p>\n<div style=\"overflow-x: auto;\" tabindex=\"0\" role=\"region\" aria-label=\"Ruby 3.4 tooling evidence and checks\">\n<table style=\"width: 100%; min-width: 780px; table-layout: auto; border-collapse: collapse; font-size: 16px; line-height: 1.55;\" aria-label=\"Ruby 3.4 tooling evidence and checks\">\n<thead>\n<tr>\n<th style=\"padding: 14px; border: 1px solid #d3dfdb; background: #edf4f0; text-align: left; vertical-align: top;\" scope=\"col\">Tool<\/th>\n<th style=\"padding: 14px; border: 1px solid #d3dfdb; background: #edf4f0; text-align: left; vertical-align: top;\" scope=\"col\">Evidence worth checking<\/th>\n<th style=\"padding: 14px; border: 1px solid #d3dfdb; background: #edf4f0; text-align: left; vertical-align: top;\" scope=\"col\">Application action<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">RuboCop<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/rubocop\/rubocop\/blob\/v1.90.0\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">1.75.0<\/a> made Prism translation the default for Ruby 3.4 analysis.<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Check TargetRubyVersion, parser engine and extension cops.<\/td>\n<\/tr>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Bootsnap<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/rails\/bootsnap\/blob\/v1.26.0\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">1.24.2 and 1.24.6<\/a> address parser-selection and detection problems.<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Check the Ruby patch, rebuild the extension and regenerate its cache.<\/td>\n<\/tr>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Spring<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/rails\/spring\/blob\/v4.7.0\/.github\/workflows\/ci.yml\" target=\"_blank\" rel=\"noopener\">4.7.0 CI<\/a> includes 3.4; this does not establish the earliest compatible release.<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Stop an existing preloader and compare commands with and without it.<\/td>\n<\/tr>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Pry<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/pry\/pry\/blob\/v0.16.0\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">0.15.2<\/a> repairs input handling when Prism detection fails.<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Exercise console input and debugger integration.<\/td>\n<\/tr>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">SimpleCov<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/simplecov-ruby\/simplecov\/blob\/v1.2.0\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">1.2.0<\/a> retains Ruby 3.2 as its minimum.<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Check actual coverage output and subprocess collation, not only a green suite.<\/td>\n<\/tr>\n<tr>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Byebug<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\"><a href=\"https:\/\/github.com\/deivid-rodriguez\/byebug\/blob\/v13.0.0\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">13.0.0<\/a> includes newer Ruby compatibility and dependency fixes.<\/td>\n<td style=\"padding: 14px; border: 1px solid #d3dfdb; text-align: left; vertical-align: top; overflow-wrap: anywhere;\">Test the installed debugger; it is incorrect to declare Byebug universally unusable.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>The new <code>it<\/code> block parameter is optional syntax. Keep explicit block parameters while both CI jobs run on 3.3 and 3.4. RSpec-core 3.13.6 explicitly accepted an unused block to quiet a separate warning. It was not an <code>it<\/code>-parameter fix, and does not establish that ordinary <code>it \"description\" do<\/code> examples broke. <a href=\"https:\/\/github.com\/rspec\/rspec\/pull\/240\" target=\"_blank\" rel=\"noopener\">RSpec change<\/a>.<\/p>\n<p>Rails 7.2 defaults enable YJIT when Ruby provides its activation API. Record whether it actually starts. Our local Ruby builds differ in YJIT availability, so their timings are not a performance comparison. <a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.2.0\/railties\/lib\/rails\/application\/configuration.rb\" target=\"_blank\" rel=\"noopener\">Defaults<\/a>, <a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.2.0\/railties\/lib\/rails\/application\/finisher.rb\" target=\"_blank\" rel=\"noopener\">activation<\/a>.<\/p>\n<h2 id=\"test-ruby-3-3-to-3-4-with-rails-held-fixed\" style=\"scroll-margin-top: 128px;\">Test Ruby 3.3 to 3.4 with Rails held fixed<\/h2>\n<p>The same generated Rails 8.0.5.1 application passed 15 tests and 47 assertions on Ruby 3.3.12 and 3.4.10. Its Rails defaults, Sprockets, Sidekiq, Redis and Devise versions stayed fixed. The local and separate Debian Bookworm container runs passed. Both runtimes compiled and served the expected CSS and processed a real Sidekiq job into the database. Selected native-library checks also passed.<\/p>\n<p>The application already resolves <code>bigdecimal<\/code> and <code>drb<\/code>. Artificially requiring <code>mutex_m<\/code> fails on 3.4 because the application does not declare or use it. That result diagnoses dependency availability; it does not contradict the passing application boot and suite.<\/p>\n<p>The <a href=\"https:\/\/www.allerin.com\/rails-checks\/ruby-3-3-to-3-4-2026-10.zip\">downloadable reproduction<\/a> contains the generated application, locked dependencies, before-and-after probes and replay instructions. AI assistance was used for research and execution. These runs describe a fixture, not an Allerin client deployment or a performance benchmark.<\/p>\n<p>Select the runtime explicitly, including the interpreter used by child processes. Our container matrix uses:<\/p>\n<pre style=\"overflow-x: auto; max-width: 100%;\"><code class=\"language-yaml\">strategy:\r\n  matrix:\r\n    ruby: [\"3.3.12\", \"3.4.10\"]\r\ncontainer:\r\n  image: ruby:${{ matrix.ruby }}-bookworm\r\n<\/code><\/pre>\n<p>In each application container, record <code>ruby -v<\/code> and <code>bundle _2.5.22_ exec ruby -e 'puts RUBY_VERSION'<\/code>, then run:<\/p>\n<pre style=\"overflow-x: auto; max-width: 100%;\"><code class=\"language-sh\">RUBYOPT=\"-W:deprecated\" bundle _2.5.22_ exec bin\/rails test --seed 6600\r\n<\/code><\/pre>\n<p>The download supplies the complete job, asset and native-library checks. Keep the two jobs through the upgrade and rollback window; a fixed sprint length is not a correctness criterion.<\/p>\n<p>Treat warnings as observations with locations and causes. The Rails suite emitted zero <code>warning:<\/code> lines on either runtime. The separate chilled-string example emitted one on 3.4, and the dependency probe emitted three migration warnings on 3.3. A zero count from this small suite cannot establish that every production path is warning-free.<\/p>\n<p>Keep the operating-system change explicit too. At the source check, the official <code>3.4<\/code> image alias selects Trixie; <code>3.4.10-bookworm<\/code> names a different Debian base. Choose the intended variant and record its image digest. Rebuild native extensions for the target Ruby and platform. Recheck the installed libvips package for Active Storage when the image changes; the Ruby version does not determine that package\u2019s version. <a href=\"https:\/\/github.com\/docker-library\/official-images\/blob\/master\/library\/ruby\" target=\"_blank\" rel=\"noopener\">Official tag mapping<\/a>, <a href=\"https:\/\/github.com\/docker-library\/ruby\/tree\/4ea2e7e222ba458994a266920e8815140bc2c901\/3.4\" target=\"_blank\" rel=\"noopener\">image definitions<\/a>.<\/p>\n<p>Ruby 3.4 also changes socket connection behavior through Happy Eyeballs, so exercise outbound HTTP, database and service connections appropriate to your application. <a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2024\/12\/25\/ruby-3-4-0-released\/#the-socket-library-now-features-happy-eyeballs-version-2-rfc-8305\" target=\"_blank\" rel=\"noopener\">Ruby 3.4 socket change<\/a>.<\/p>\n<h2 id=\"what-to-do-this-week\" style=\"scroll-margin-top: 128px;\">What to do this week<\/h2>\n<ol>\n<li>Record the Rails patch, Ruby versions, dependency lock and the blocker, if any, to keeping Rails fixed.<\/li>\n<li>Run the same suite and representative jobs on both Rubies with deprecation warnings enabled. Separate dependency failures, literal warnings and output-only assertions.<\/li>\n<li>Review <code>.ruby-version<\/code>, <code>.tool-versions<\/code> where used, the Dockerfile\u2019s Ruby argument or tag, and the CI matrix. Check the Gemfile Ruby constraint and lockfile\u2019s <code>RUBY VERSION<\/code> and <code>PLATFORMS<\/code> too; platforms identify build targets, not the interpreter version.<\/li>\n<li>Rebuild and test the deployment image, including native extensions, assets, connections and background workers. Retain the working prior image for rollback.<\/li>\n<li>Deploy the Ruby change independently once these checks pass. Start the Rails branch from that verified state.<\/li>\n<\/ol>\n<h2 id=\"ruby-4-0-is-a-separate-next-hop\" style=\"scroll-margin-top: 128px;\">Ruby 4.0 is a separate next hop<\/h2>\n<p>Released on 25 December 2025, Ruby 4.0 moved <code>ostruct<\/code>, <code>pstore<\/code>, <code>benchmark<\/code>, <code>logger<\/code>, <code>rdoc<\/code>, <code>win32ole<\/code>, <code>irb<\/code>, <code>reline<\/code>, <code>readline<\/code> and <code>fiddle<\/code> to bundled gems. Ruby 3.4.0\u2019s warning map listed nine future candidates under the then-planned label <code>3.5.0<\/code>; <code>readline<\/code> was explicitly excluded from warnings. Ruby 3.4.10 updates those labels to <code>4.0.0<\/code>; <code>readline<\/code> remains excluded. The warning map and the eventual release list are different records. <a href=\"https:\/\/github.com\/ruby\/ruby\/blob\/v3_4_0\/lib\/bundled_gems.rb\" target=\"_blank\" rel=\"noopener\">3.4.0 warning map<\/a>, <a href=\"https:\/\/github.com\/ruby\/ruby\/blob\/v3_4_10\/lib\/bundled_gems.rb\" target=\"_blank\" rel=\"noopener\">3.4.10 map<\/a>, <a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2025\/12\/25\/ruby-4-0-0-released\/\" target=\"_blank\" rel=\"noopener\">4.0 release<\/a>.<\/p>\n<p>ZJIT is opt-in, and the 4.0 release announcement cautions against production deployment of that new compiler. This fixture did not test Ruby 4.0. A permissive gemspec or selected CI cell cannot certify an application for that next hop.<\/p>\n<p>For an application-specific sequence, use Allerin\u2019s <a href=\"https:\/\/www.allerin.com\/services\/rails-upgrades\">Rails upgrade guide<\/a>.<\/p>\n<p>Runtime versions, commands, expected failures and limitations are included in the downloadable reproduction. Facts checked 7 September 2026.<\/p>\n<details>\n<summary>Primary sources<\/summary>\n<ol>\n<li><a href=\"https:\/\/www.ruby-lang.org\/en\/downloads\/branches\/\" target=\"_blank\" rel=\"noopener\">Ruby branches<\/a><\/li>\n<li><a href=\"https:\/\/www.ruby-lang.org\/en\/downloads\/\" target=\"_blank\" rel=\"noopener\">release list<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v6.1.7.10\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">Rails 6.1.7.10 gemspec<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.0.10\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">Rails 7.0.10 gemspec<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.1.6\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">Rails 7.1.6 gemspec<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.2.3.2\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">Rails 7.2.3.2 gemspec<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v8.0.5.1\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">Rails 8.0.5.1 gemspec<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v8.1.3.1\/rails.gemspec\" target=\"_blank\" rel=\"noopener\">Rails 8.1.3.1 gemspec<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/buildkite-config\/blob\/85fd52e62c9c0b9b1d5ea4c574bafba5597db030\/pipelines\/rails-ci\/pipeline.rb\" target=\"_blank\" rel=\"noopener\">pipeline<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/buildkite-config\/blob\/85fd52e62c9c0b9b1d5ea4c574bafba5597db030\/lib\/buildkite\/config\/build_context.rb\" target=\"_blank\" rel=\"noopener\">selection rules<\/a><\/li>\n<li><a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2017\/12\/25\/ruby-2-5-0-released\/\" target=\"_blank\" rel=\"noopener\">Ruby 2.5\u2019s 2017 release<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/ruby\/ruby\/blob\/v3_4_0\/NEWS.md#stdlib-updates\" target=\"_blank\" rel=\"noopener\">Ruby 3.4 library changes<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.1.0\/activesupport\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">7.1 changelog<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.0.9\/activesupport\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">7.0.9 changelog<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/ruby-concurrency\/concurrent-ruby\/blob\/v1.3.5\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">Dependency change<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.0.9\/activesupport\/lib\/active_support\/logger_thread_safe_level.rb\" target=\"_blank\" rel=\"noopener\">7.0.9 source<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.1.0\/activesupport\/lib\/active_support\/logger_thread_safe_level.rb\" target=\"_blank\" rel=\"noopener\">7.1.0 source<\/a><\/li>\n<li><a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2015\/12\/25\/ruby-2-3-0-released\/\" target=\"_blank\" rel=\"noopener\">Ruby 2.3 release<\/a><\/li>\n<li><a href=\"https:\/\/bugs.ruby-lang.org\/issues\/20205\" target=\"_blank\" rel=\"noopener\">transition design<\/a><\/li>\n<li><a href=\"https:\/\/docs.ruby-lang.org\/en\/4.0\/syntax\/comments_rdoc.html#label-frozen_string_literal+Directive\" target=\"_blank\" rel=\"noopener\">Ruby 4.0 string directive<\/a><\/li>\n<li><a href=\"https:\/\/bugs.ruby-lang.org\/issues\/20433\" target=\"_blank\" rel=\"noopener\">Design discussion<\/a><\/li>\n<li><a href=\"https:\/\/bugs.ruby-lang.org\/issues\/16495\" target=\"_blank\" rel=\"noopener\">Quote consistency<\/a><\/li>\n<li><a href=\"https:\/\/bugs.ruby-lang.org\/issues\/19117\" target=\"_blank\" rel=\"noopener\">method-owner backtraces<\/a><\/li>\n<li><a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2023\/12\/25\/ruby-3-3-0-released\/\" target=\"_blank\" rel=\"noopener\">Ruby 3.3 parser introduction<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rubocop\/rubocop\/blob\/v1.90.0\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">RuboCop changelog<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/bootsnap\/blob\/v1.26.0\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">Bootsnap changelog<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/spring\/blob\/v4.7.0\/.github\/workflows\/ci.yml\" target=\"_blank\" rel=\"noopener\">4.7.0 CI<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/pry\/pry\/blob\/v0.16.0\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">Pry changelog<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/simplecov-ruby\/simplecov\/blob\/v1.2.0\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">SimpleCov changelog<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/deivid-rodriguez\/byebug\/blob\/v13.0.0\/CHANGELOG.md\" target=\"_blank\" rel=\"noopener\">Byebug changelog<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rspec\/rspec\/pull\/240\" target=\"_blank\" rel=\"noopener\">RSpec change<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.2.0\/railties\/lib\/rails\/application\/configuration.rb\" target=\"_blank\" rel=\"noopener\">Defaults<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/rails\/rails\/blob\/v7.2.0\/railties\/lib\/rails\/application\/finisher.rb\" target=\"_blank\" rel=\"noopener\">activation<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/docker-library\/official-images\/blob\/master\/library\/ruby\" target=\"_blank\" rel=\"noopener\">Official tag mapping<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/docker-library\/ruby\/tree\/4ea2e7e222ba458994a266920e8815140bc2c901\/3.4\" target=\"_blank\" rel=\"noopener\">image definitions<\/a><\/li>\n<li><a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2024\/12\/25\/ruby-3-4-0-released\/#the-socket-library-now-features-happy-eyeballs-version-2-rfc-8305\" target=\"_blank\" rel=\"noopener\">Ruby 3.4 socket change<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/ruby\/ruby\/blob\/v3_4_0\/lib\/bundled_gems.rb\" target=\"_blank\" rel=\"noopener\">3.4.0 warning map<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/ruby\/ruby\/blob\/v3_4_10\/lib\/bundled_gems.rb\" target=\"_blank\" rel=\"noopener\">3.4.10 map<\/a><\/li>\n<li><a href=\"https:\/\/www.ruby-lang.org\/en\/news\/2025\/12\/25\/ruby-4-0-0-released\/\" target=\"_blank\" rel=\"noopener\">4.0 release<\/a><\/li>\n<\/ol>\n<\/details>\n","protected":false},"excerpt":{"rendered":"<p>A tested Ruby upgrade with Rails held fixed explains bundled gems, chilled strings, parser tooling and output-sensitive tests, with a downloadable reproduction.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[2037],"tags":[2059,2058,2038,2057,2056],"class_list":["post-14877","post","type-post","status-publish","format-standard","hentry","category-ruby-on-rails","tag-bundler","tag-prism","tag-rails-upgrades","tag-ruby-3-4","tag-ruby-upgrades"],"_links":{"self":[{"href":"https:\/\/www.allerin.com\/blog\/wp-json\/wp\/v2\/posts\/14877","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.allerin.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.allerin.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.allerin.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.allerin.com\/blog\/wp-json\/wp\/v2\/comments?post=14877"}],"version-history":[{"count":3,"href":"https:\/\/www.allerin.com\/blog\/wp-json\/wp\/v2\/posts\/14877\/revisions"}],"predecessor-version":[{"id":14893,"href":"https:\/\/www.allerin.com\/blog\/wp-json\/wp\/v2\/posts\/14877\/revisions\/14893"}],"wp:attachment":[{"href":"https:\/\/www.allerin.com\/blog\/wp-json\/wp\/v2\/media?parent=14877"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.allerin.com\/blog\/wp-json\/wp\/v2\/categories?post=14877"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.allerin.com\/blog\/wp-json\/wp\/v2\/tags?post=14877"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}