Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

週刊Railsウォッチ: method_missingの引数を'...'に置き換え、JRuby Prism、Sidekiqのしくみほか(20240306)

こんにちは、hachi8833です。
超久しぶりに対面でのつっつき会を開催できました😂。

週刊Railsウォッチについて

  • 各記事冒頭には🔗でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • お気づきの点がありましたら@hachi8833までメンションをいただければ確認・対応いたします🙏

TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)

🔗Rails: 先週の改修(Rails公式ニュースより)

🔗 assert_broadcastsがブーリアンの代わりにブロードキャスト済みのメッセージを返すようになった

assert_broadcastsが、ブロードキャスト済みのメッセージを返すようになった。
これにより、ブロードキャスト済みメッセージのさらなる分析がやりやすくなる。

message = assert_broadcasts("test", 1) do
  ActionCable.server.broadcast "test", "message"
end
assert_equal "message", message

messages = assert_broadcasts("test", 2) do
  ActionCable.server.broadcast "test", { message: "one" }
  ActionCable.server.broadcast "test", { message: "two" }
end

assert_equal 2, messages.length
assert_equal({ "message" => "one" }, messages.first)
assert_equal({ "message" => "two" }, messages.last)

Alex Ghiculescu
同Changelogより

このプルリクは#47025でのassert_emailの改修と同様、Action Cableのassert_broadcastsがブロードキャスト済みのメッセージを返すようになった。これは以下のようにさらに分析可能になる。

    messages = assert_broadcasts("test", 2) do
      ActionCable.server.broadcast "test", { message: "one" }
      ActionCable.server.broadcast "test", { message: "two" }
    end
    assert_equal 2, messages.length
    assert_equal({ "message" => "one" }, messages.first)
    assert_equal({ "message" => "two" }, messages.last)

これは、ブロードキャストされるメッセージ数が多い場合や、データの一部の要素だけを照合したい場合に有用。assert_broadcast_onはどちらのシナリオでもうまくいかない。

同PRより

つっつきボイス:「ブロードキャスト済みのメッセージを返す前のことは書かれていなかったんですが、以前はtrue/falseを返していたんですね」「アサーションでブロードキャストメッセージの内容も調べられるのはいい👍」

参考: Rails API assert_broadcasts -- ActionCable::Channel::TestCase::Behavior

🔗 テストよもやま話

「ところで、今はRailsアプリのテストでminitestとRSpecとどちらがよく使われているんでしょうか?」「今やってるプロジェクトはRSpec」「個人アプリでminitest使ってます」「Rails作者のDHHがRSpecが好きでないというのは昔から有名で、他の人が使うのはいいけど自分は使いたくないというスタンスですね」

「一般的にですけど、ライブラリやフレームワークを対象とするテストはminitestみたいな比較的シンプルなアサーションの方が望ましいことが多いでしょうね: 一方、特にビジネスユースケースを伴うアプリだとRSpecのcontextdescribeのようなものがビジネスを説明するうえでしっくりくると思いますし、特にcontextと言えばビジネスコンテキストを連想しやすいしステートを持っている感じを出せますね」「なるほど」「もちろんライブラリやフレームワークにもステートがあることもありますけど、一般にライブラリやフレームワークはどちらかというとステートがあまり前面に出てこないような印象があるのでminitestを好む気持ちもわからなくもないかな: とはいえRailsぐらい大規模になるとそうもいかないでしょうけど」「rails newのオプションを網羅するテストなんかはベタ書きだと大変そうですね」

「ところでminitestはパラレル実行できるけどRSpecはそのままだとパラレルにできないんでしたっけ?」「大昔はrrrspecで分散実行したりしていたこともありましたけど、もうだいぶ前からparallel_testsでパラレル実行できますよ」「あ、知りませんでした😅」

参考: Rails - Rspec で paralells test を利用して並列処理する ( create / migrate / prepar
参考: さようならrrrspec、いままで速度をありがとう - 弥生開発者ブログ

grosser/parallel_tests - GitHub

🔗 has_one関連付けの自動保存のバグを修正

外部キー属性が変更されていない場合に設定されるhas_one関連付けの自動保存を修正。

この振る舞いはbelongs_toの自動保存とも一貫しておらず、外部キー属性がread-onlyとマーキングされている場合にActiveRecord::ReadOnlyAttributeErrorなどの意図しない副作用が発生する可能性がある。

Joshua Young
同Changelogより

動機/背景

修正: #50897

類似プルリク: #46759

詳細

ActiveRecord::AutosaveAssociation#save_has_one_associationが、子レコード上の外部キー属性が変更された場合にのみ外部キー属性を更新するよう修正。これにより、belongs_to関連付けの振る舞いと一貫するようになり、属性が変更されなかった場合にActiveRecord::ReadOnlyAttributeErrorが発生しないようになる。
同PRより


つっつきボイス:「has_oneってhas_manybelongs_toと比べてあまり使われてない分バグが見つかりやすいんですよね」「たいていhas_manybelongs_toの方が圧倒的に注目されていますよね」「readonlyな属性を変更せずに保存したらエラーになるのはバグ」「修正はこれだけですね↓」

# activerecord/lib/active_record/autosave_association.rb#L442
      def save_has_one_association(reflection)
        association = association_instance_get(reflection.name)
        record      = association && association.load_target
        if record && !record.destroyed?
          autosave = reflection.options[:autosave]
          if autosave && record.marked_for_destruction?
            record.destroy
          elsif autosave != false
            primary_key = Array(compute_primary_key(reflection, self)).map(&:to_s)
            primary_key_value = primary_key.map { |key| _read_attribute(key) }
            if (autosave && record.changed_for_autosave?) || _record_changed?(reflection, record, primary_key_value)
              unless reflection.through_reflection
                foreign_key = Array(reflection.foreign_key)
                primary_key_foreign_key_pairs = primary_key.zip(foreign_key)

                primary_key_foreign_key_pairs.each do |primary_key, foreign_key|
-                 record[foreign_key] = _read_attribute(primary_key)
+                 association_id = _read_attribute(primary_key)
+                 record[foreign_key] = association_id unless record[foreign_key] == association_id
                end
                association.set_inverse_instance(record)
              end
              saved = record.save(validate: !autosave)
              raise ActiveRecord::Rollback if !saved && autosave
              saved
            end
          end
        end
      end

🔗 where.associatedのバグを修正

この修正によって、スコープ内の既存のJOINに基づいて、適切なJOIN種別(INNER JOINまたはLEFT OUTER JOIN)を用いて関連付けがJOINされるようになる。

これにより、既存のJOIN種別が意図せずオーバーライドされることを防ぎ、一貫したSQLクエリが生成されるようになる。

例:

# `associated`では`JOIN`ではなく`LEFT JOIN`が使われる
Post.left_joins(:author).where.associated(:author)

Saleh Alhaddad
同Changelogより

動機/背景

Railsの現在のwhere.associatedメソッドは、関連付けられたレコードをinner joinでフィルタすることしかできず、クエリで既存のJOIN種別がオーバーライドされる可能性がある。この修正によって、スコープ内の既存のJOINに基づいて、適切なJOIN種別(INNER JOINまたはLEFT OUTER JOIN)を用いて関連付けがJOINされるようになる。これにより、既存のJOIN種別が意図せずオーバーライドされることを防ぎ、一貫したSQLクエリが生成されるようになる。

例:

 User.left_outer_joins(:orders).where.associated(:orders).count

修正前のクエリ:

SELECT COUNT(*) FROM "users" INNER JOIN "orders" ON "orders"."user_id" = "users"."id" WHERE "orders"."id" IS NOT NULL

問題修正後のクエリ:

SELECT COUNT(*) FROM "users" LEFT OUTER JOIN "orders" ON "orders"."user_id" = "users"."id" WHERE "orders"."id" IS NOT NULL

この機能強化によって、関連付けられたデータへのクエリを開発者がさらに柔軟に実行できるようになり、以下のようなシナリオが容易になる。

  • 投稿の一部に著者が割り当てられていない場合でも、著者付きの投稿リストを取得する(left_joinsを利用)
  • ユーザーが紐づけられていない孤立コメントを含めて、特定ユーザーと関連付けられているコメントリストを取得する(複数のJOIN種別を利用)

詳細

このプルリクにおける重要な改善点は、スコープ内の既存のJOINに基づいて、適切なJOIN種別(INNER JOINまたはLEFT OUTER JOIN)を用いて関連付け同士がJOINされるようになることである。これによって、既存のJOIN種別が意図せずオーバーライドされることを防ぎ、生成されるSQLクエリの一貫性が高まる。

追加情報

この改良は、さまざまなフォーラムやディスカッションでRails開発者によって明らかにされた共通要件に基づいている。これと類似した機能は特定の有名なORM拡張でも普及しており、その有用性が強調されている。この実装は、既存のコードベースの明確さと一貫性を維持するように作られている。

注: この説明はドラフトであり、各自の実装の詳細やプロジェクトの事情に合わせて調整が必要。

FYI: このプルリクがマージされたら、別のプルリクでmissingメソッドをチェックしてこの問題を修正する予定。

(メモ: パフォーマンスは修正前後でほとんど変わらないらしい)

同PRより


つっつきボイス:「このバグは、LEFT OUTER JOINだったクエリがassociatedでINNER JOINに変わったりするのを修正したということですね」「associatedって、missingの逆のメソッドじゃなかったかな?」「そういえばありましたね↓」「Rails 7に入った、関連先に物理レコードが存在するものだけを取ってくる機能だった(ウォッチ20201208)」「missingはもっと前からありますね」

Rails 7: 関連付けのあるレコードを取れる'associated'クエリメソッドが追加(翻訳)

参考: Rails API missing -- ActiveRecord::QueryMethods::WhereChain

associatedmissingって本編コードでは普通はあまり使わないはずのもので、ありそうな使い方としてはproductionデータで何らかの原因でバリデーションをすり抜けて、ないはずのレコードがあったり、あるはずのレコードがないといった異常データをメンテナンスするときの利用を主に想定しているんじゃないかな」「ふむふむ」「belongs_toなどでdependent: :nullifyとかoptional: trueとかを使ったり、あるいは生SQL使ってたりするとそういう孤立レコードができる可能性があるけど、そうでもなければ普通はできないはずなんですよね」「missingを使うことがあるとすれば、トランザクション内で一時的にできる孤立レコードをバッチ更新したいときにmissingで孤立レコードを取り直すとかですかね」「そういう場合はありうるし、やってはいけないわけではないけど、なるべくならActive Recordで1個ずつ正当な方法で処理していく方が望ましいでしょうね」

「ところで、サンプルコードでLEFT OUTER JOINした後にassociatedでまたLEFT OUTER JOINするのってどういうシチュエーションなのかよくわからないです↓」「これは単なる修正内容を説明するときのクエリなんじゃないかな」「left_outer_joinsassociatedを通すとINNER JOINになってしまうのはよろしくないので元のLEFT OUTER JOINを変えないように修正したということでしょうね」

User.left_outer_joins(:orders).where.associated(:orders).count

associatedmissingは主にそういうデータ不整合を解消するときに使う印象があるかな」

🔗 リダイレクトのクエリパラメータのログ出力にconfig.filter_parametersが効くようになった

元の#21045は8年前のプルリクだそうです。

リダイレクト先のパラメータをフィルタする機能を追加。

config.filter_parametersを用いてフィルタが必要なものとマッチさせる。
結果は以下のようになる。

Redirected to http://secret.foo.bar?username=roque&password=[FILTERED]

修正: #14055

Roque PinelTrevor Turktonytonyjan
同Changelogより


つっつきボイス:「リダイレクトしたときにリダイレクト先のクエリパラメータがそのままログに出力されていたのね」「リダイレクトのURLにもconfig.filter_parametersのフィルタが効くように修正したんですね」「そもそもログインで?username=ユーザー名&password=パスワードみたいにクエリパラメータに露出させる書き方って普通しないと思いますけどね」「ですよね」「ごくたま〜に見かけなくもないですけど」「秘密でも何でもないワンタイムのトークンぐらいだったらありますね」

# actionpack/lib/action_dispatch/http/filter_redirect.rb#L5
module ActionDispatch
  module Http
    module FilterRedirect
      FILTERED = "[FILTERED]" # :nodoc:
      def filtered_location # :nodoc:
        if location_filter_match?
          FILTERED
        else
-         location
+         parameter_filtered_location
        end
      end
...
+
+     def parameter_filtered_location
+       uri = URI.parse(location)
+       unless uri.query.nil? || uri.query.empty?
+         uri.query.gsub!(FilterParameters::PAIR_RE) do
+           request.parameter_filter.filter($1 => $2).first.join("=")
+         end
+       end
+       uri.to_s
+     end

参考: § 3.2.33 config.filter_parameters -- Rails アプリケーションの設定項目 - Railsガイド

「デフォルトのフィルタは部分一致なので、以下の名前を部分的にでも含むものはフィルタで除外されるようになっていますよね↓」

# Railsガイドより
Rails.application.config.filter_parameters += [
  :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
]

「この種のフィルタは慎重な方に倒すのが基本ですね: たとえばログに個人を特定できるような情報やセンシティブな情報が含まれてしまっていると、情報取扱い上顧客がそのログを開発会社に出せなくなって作業に支障が生じる可能性があるので、そういう情報は極力ログなどに出ないようにしたい」「セキュリティ上重大な情報でないとしても、個人の特定につながるような情報が含まれてしまうと取り扱い注意になってしまいますよね」「顧客の正社員しか扱えなくなったりとかですね」

🔗 Logger.logger_outputs_to?にファイル名の文字列やFileオブジェクトを渡せるようになった。

Logger.logger_outputs_to?の出力先でファイル名もサポートするようになった。

Logger.logger_outputs_to?('/var/log/rails.log')

Christian Schmidt
同Changelogより

Logger.logger_outputs_to?でサポートしている出力先はSTDOUTSTDERRのみで、Fileオブジェクトやファイル名の文字列がサポートされていなかった。
同PRより


つっつきボイス:「今までは標準出力と標準エラーしか指定できなかったのをファイルパスでも渡せるようにしたというシンプルな修正ですね」

# activesupport/lib/active_support/logger.rb#L20
    def self.logger_outputs_to?(logger, *sources)
      loggers = if logger.is_a?(BroadcastLogger)
        logger.broadcasts
      else
        [logger]
      end

      logdevs = loggers.map { |logger| logger.instance_variable_get(:@logdev) }
-     logger_sources = logdevs.filter_map { |logdev| logdev.dev if logdev.respond_to?(:dev) }
+     logger_sources = logdevs.filter_map { |logdev| logdev.try(:filename) || logdev.try(:dev) }

-     sources.intersect?(logger_sources)
+     normalize_sources(sources).intersect?(normalize_sources(logger_sources))
    end
...
+   private
+     def self.normalize_sources(sources)
+       sources.map do |source|
+         source = source.path if source.respond_to?(:path)
+         source = File.realpath(source) if source.is_a?(String) && File.exist?(source)
+         source
+       end
+     end
  end

参考: Rails API logger_outputs_to? -- ActiveSupport::Logger

🔗 method_missingの引数を...などに置き換えた

キーワード引数が分離されて以来、...記法の方がシンプルかつより正しい。
同PRより


つっつきボイス:「これと次のプルリクは永和システムマネジメントさんが主催している"Rails / OSS パッチ会オンライン"↓のDiscordでたまたま見かけたもので、これはbyrootさんによるリファクタリングです」

参考: Rails / OSS パッチ会オンライン 2024年2月のお知らせ - ESM アジャイル事業部 開発者ブログ

「従来のmethod_missingの引数がごっそり新しい...記法などで置き換わってる」「文字通りRubyの書き方を現代化してますね」

# actionpack/lib/action_dispatch/http/mime_type.rb#L329
-     def method_missing(method, *args)
+     def method_missing(method, ...)
        if method.end_with?("?")
          method[0..-2].downcase.to_sym == to_sym
        else
          super
        end
      end
# actionpack/lib/action_dispatch/system_test_case.rb#L181
-     def method_missing(name, *args, &block)
+     def method_missing(name, ...)
        if url_helpers.respond_to?(name)
-         url_helpers.public_send(name, *args, &block)
+         url_helpers.public_send(name, ...)
        else
          super
        end
      end

*args, **options, &blockみたいな長い引数も...で置き換わってる↓」「新人向けに説明すると、*が付いた仮引数はordered arguments(値のみの引数で、順序がある)をリストとして受け取る、**が付いた仮引数はnamed arguments(名前つき引数、順序は入れ替え可能)をHashとして受け取る、&が付いた仮引数は呼び出し時に渡されたブロックをProcとして受け取る、という昔からある書き方ですね」「書くときはその順序で書かなければいけないヤツ」

# actionview/lib/action_view/helpers/tag_helper.rb#L337
-         def method_missing(called, *args, **options, &block)
-           name = called.to_s.dasherize
+         def method_missing(called, ...)
+           name = called.name.dasherize

            TagHelper.ensure_valid_html5_tag_name(name)

-           tag_string(name, *args, **options, &block)
+           tag_string(name, ...)
          end
      end

...はRuby 2.7で入った新構文で、仮引数で受け取ったものをそのままforwardする記法でしたね」

Ruby: "uselessシンタックスシュガー"シリーズ「引数のforwarding」(翻訳)

「その後Ruby 3.0で(name, ...)みたいに残りの引数をまとめてforwardすることも可能になってましたね↓」

Ruby 3: 引数をforwardする`...`記法が第2パラメータでも使えるようになった(翻訳)

...記法にすれば、受け取ったものを中継するだけのメソッドで引数の名前を考えずに済むのがとっても嬉しい」「しかも...にすれば"全部受け取って丸投げするだけだよ"という意図も示せますよね」「...は変数名に使えない文字だから中に何かがあっても参照しようがない😆」「たしかに😆」

「以前だとargsとかargumentsとかoptionとかoptsのような引数名ってライブラリやプロジェクトごとにバラつきがちでしたよね」「そうなんですよ...」「プログラミングで最も時間がかかるのは名前を考えることだとよく言われるくらいなので、命名を減らせるのはとてもありがたい👍」

🔗 文字列をTimeDateTimeに型変換したときのタイムゾーンオフセットのバグを修正

文字列をTimeDateTimeに型変換するときにタイムゾーンオフセットの分(minute)の値がマイナスだと正しく計算されないバグを修正。

Akira Matsuda
同Changelogより

このパッチは、Active ModelのTime型キャスターが、指定の文字列内にあるマイナスのオフセットを正しく扱っていないバグを修正する。

背景/詳細

指定した文字列内のタイムゾーンにマイナスのオフセットがある場合は時(hour)と分(minute)の値を両方とも正負反転する必要があるが、現在のコードではhourだけが正負反転されている。

たとえばNewfoundland Time Zone (UTC-03:30)の場合、オフセット部分は"-03:30"となり、これは「-3時間と-30分」として扱わなければならないが、これまでは「-3時間と+30分」として算出されていたため、実際の時刻より1時間進んだ値を返していた。

追加情報

Time自身を解析するのは専門家でないと難しすぎる。このバグは、自分が#46868で提案しているRuby組み込みのTimeパーサーへの差し替えの理由付けになるだろう。また、このバグはTimeのプロである@nobuによって#19293(コメント)で発見および報告された(感謝!)。
同PRより


つっつきボイス:「nobuさんが見つけて報告したタイムゾーンのオフセットのバグをa_matsudaさんが修正したプルリクです」「"-03:30"-3時間と-30分が正しいのに分だけ誤って+30分になってたのか!」「あ〜なるほど」「しかもオフセットがマイナスかつ30分の国でのみ起きるレアなバグ」

「TimeとかDateTimeの扱いはただでさえ難しくて気を遣うのに(ウォッチ20210713)、オフセットが1時間単位じゃなくて30分の国があるのってつらい」「時間表記は60進法と24進法が混じっていて表記は10進数だし、しかもゼロ始まりだし」「プルリクにも書かれているように専門家じゃないと難しいですよね」「奇しくも今日は閏年で2/29なので(つっつきの日)、この日しか起きないバグが起きたりしているようですね」

「ちなみにプルリクにあったAMoって何だろうと思ったらActive Modelのことでした」「ARならActive RecordしかないけどAMだけだとAction MailerやAction Mailboxもあって一意に定まらないからでしょうね」


後で調べると、30分ずれの国に加えて45分ずれの国もありました↓。

参考: Half Hour and 45-Minute Time Zones

🔗Rails

🔗 Sidekiqが動くしくみ(Ruby Weeklyより)


つっつきボイス:「Railsで非同期ジョブ処理によく使われるSidekiqの基本的なしくみを詳しく解説している記事です」「ちょっと長いけど、Sidekiqについて学びたい人は頑張って読んでみるといいと思います👍」

sidekiq/sidekiq - GitHub

Rails: Solid Queueで重要なUPDATE SKIP LOCKEDを理解する(翻訳)

「最近はSolid Queue↑がRailsのデフォルトジョブエンジンに取り入れられることになったけど、Sidekiqとかが使われなくなるとは思えないですね」「SidekiqやRedisなど実績のあるものは今後も使い続けられると思います: BPS社内でbabaさんたちと話したときにも話題にしたんですが、Solid QueueはRDBにジョブエンジンの責務も負わせることになり、特にエンタープライズ系のアプリや多数のジョブをさばくようなアプリではRDBの仕事をあまり増やしたくないので、SidekiqやRedisなどは今後も普通に使っていくでしょうね」

🔗 Turbo 8のモーフィングを深堀りする(Ruby Weeklyより)


つっつきボイス:「先ごろリリースされたTurbo 8の2本立て記事で、2本目の記事の下には、Turbo 8で使われているidiomorphを動かせるplaygroundが付いていました」

basecamp/idiomorph - GitHub

Rails: フルスタックRailsの未来(1)Turbo Morph Drive(翻訳)

🔗 testcontainers.com: テスト向けのDockerコンテナ実行環境をコードから起動して操作可能にする

testcontainers/testcontainers-ruby - GitHub


つっつきボイス:「このTestcontainersというサービスがRubyにも対応しているので取り上げてみました」「docker composeではcompose.yamlですべての環境をセットアップしなければならないけど、Testcontainersを使うとコンテナの起動後にもコードからプログラマブルに操作できるというものらしい: 何となくだけど、Railsのテストというよりは主に単一の実行ファイル形式のテストから使い捨てコンテナを利用したい人向けなのかも?」

「単に使い捨てのコンテナがコード内から起動して利用できるだけなら特に必要は感じないけど、起動後にプログラムからコンテナ内の設定をテストごとにある程度操作したりできるんだとしたらちょっといいかも」「PostgreSQLやMySQLやRedisやSeleniumなどのコンテナが用意されているんですね」「Seleniumはなくてもいいけど、RabbitMQやRedisのような複雑なサービスを本番同様にテスト環境でコードの中から動的に使い捨てることができるんなら使ってみたいかも」

# 同リポジトリより
container = Testcontainers::DockerContainer.new("redis:6.2-alpine").with_exposed_port(6379)
container.start
host = container.host
port = container.mapped_port(6379)

「Testcontainersサイトにあるこの記事が参考になりそうですね↓」「ありがとうございます🙏」

参考: What is Testcontainers, and why should you use it?

Testcontainersで解決される問題:

  • 事前にプロビジョニングされた統合テストインフラを用意する必要がない。
    Testcontainers APIはテストの実行前に必要なサービスを提供し、インフラを定義するコードを実際のテストコードのすぐ近くに書ける。

  • 各パイプラインは分離されたサービスのセットで実行されるため、複数のビルドパイプラインがパラレル実行される場合でもデータ競合の問題は発生しない。

  • 単体テストを実行するのと同じように、統合テストをIDEから直接実行可能になる。
    変更のプッシュや、CI統合テストの実行完了を待つ必要がない。

  • テストの実行後、Testcontainers はコンテナを自動的にクリーンアップする。
    同記事より

🔗 その他Rails

参考: Rails Girls São Paulo


つっつきボイス:「The Rails FoundationとDoximityがブラジルのサンパウロで活動しているRails Girls 2024のスポンサーになったという記事です」「う、ポルトガル語わからん」

「Rails Girlsって日本の団体しか知らなかったんですが、他の国にもあるんですね」「フィンランドのヘルシンキで最初に設立されたRails Girls以外にもいくつかの国でも活動していて、日本のRails Girlsもほぼ同じぐらい歴史がありますよ」「そうなんですね」

参考: Rails Girls -- ヘルシンキ
参考: Rails Girls - Japanese

🔗Ruby

🔗 JRubyのPrismが登場(Ruby Weeklyより)

参考: Prism pluggable integration work by enebo · Pull Request #8103 · jruby/jruby


つっつきボイス:「少し前にRubyの新パーサーであるPrismのJRuby版がリリースされたそうです」「お〜すごい!」「今でこそJRubyはRuby 3.1互換ですけど、以前はRubyのバージョンアップになかなか追いつけなくて苦労していましたよね(ウォッチ20221207)」「以前は移植のためにJRubyで独自パーサーをメンテしていたけど、Prismの目標のひとつがJRubyを支援することだったはずでしたね」

参考: Home — JRuby.org

Rubyパーサーを一新するprism(旧YARP)プロジェクトの全容と将来(翻訳)


今回は以上です。

バックナンバー(2024年度第1四半期)

週刊Railsウォッチ: Rails 8でSprocketsがPropshaftに置き換わる、devcontainerサポートほか(20240228)

ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。

Rails公式ニュース

Ruby Weekly


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。