nobo's blog

プログラミング、日常、etc...

Active Supportのpluralizeメソッド見てみる

Active Record の基礎 2.1 命名規約

Active Record の基礎 - Railsガイド

Railsでは、データベースのテーブル名を探索するときに、モデルのクラス名を複数形にした名前で探索します。たとえば、Bookというモデルクラスがある場合、これに対応するデータベースのテーブルは複数形の「books」になります。Railsの複数形化メカニズムは非常に強力で、不規則な語でも複数形/単数形に変換できます(person <-> peopleなど)。これにはActive Supportの pluralizeメソッドが使われています。

ここ気になっていたので、Active Supportの pluralizeメソッドを見ていく。

Active Support コア拡張機能 - Railsガイド

ここにあるようにレシーバを「複数形」にしたものを返す。

If the optional parameter +locale+ is specified, the word will be pluralized as a word of that language. By default, this parameter is set to :en. You must define your own inflection rules for languages other than English.

オプションのパラメータ +locale+ が指定された場合、 指定された言語の単語として複数形化されます。 デフォルトでは、このパラメータは :en に設定されています。 英語以外の言語については、独自の活用規則を定義する必要があります。

らしく、locale によって変えられるんだ。初めて知った。

  def pluralize(count = nil, locale = :en)
    locale = count if count.is_a?(Symbol)
    if count == 1
      dup
    else
      ActiveSupport::Inflector.pluralize(self, locale)
    end
  end

count if count.is_a?(Symbol) となっているけど、count って symbol が渡されるんだ。数値かと思った。

しかも count の結果を locale に入れている?

あー、count:ja とかが入っている場合は、else' に落ちて ActiveSupport::Inflector.pluralize(self, locale)locale を渡しているのかー。なるほど。

dup ってなんだっけ。「自身と同じクラスのオブジェクトを作成後、自身のインスタンス変数を全て新たに作成したオブジェクトにコピーします」らしい。なるほど。

Rake::Cloneable#dup (Ruby 4.0 リファレンスマニュアル)

ActiveSupport::Inflector.pluralize(self, locale) って何してるんだ?

rails/activesupport/lib/active_support/inflector/methods.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

  def pluralize(word, locale = :en)
    apply_inflections(word, inflections(locale).plurals, locale)
  end

apply_inflections を呼んでいる。

rails/activesupport/lib/active_support/inflector/methods.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

inflections(locale).plurals って何を返すの?

rails/activesupport/lib/active_support/inflector/inflections.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

  def inflections(locale = :en)
    if block_given?
      yield Inflections.instance(locale)
    else
      Inflections.instance_or_fallback(locale)
    end
  end

なるほどー。ブロックが渡されることもあるんだね。 大体は Inflections.instance_or_fallback(locale) に落ちるのかな? じゃあ Inflections.instance_or_fallback(locale) はなんぞや

rails/activesupport/lib/active_support/inflector/inflections.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

  def self.instance_or_fallback(locale)
    # :en であれば @__en_instance__ == :en, なければ インスタンス が入る
    return @__en_instance__ ||= new if locale == :en

    I18n.fallbacks[locale].each do |k|
      return @__en_instance__ if k == :en && @__en_instance__
      # それ以外の言語だったら それを返す
      # @__instance__ は Concurrent::Map.new
      return @__instance__[k] if @__instance__.key?(k)
    end
    instance(locale)
  end

@__en_instance__ って何? チャッピー に聞いたところ、普通のインスタンス変数とのこと。 Ruby コミュニティでよくある 慣習的な命名。らしく、メモ化用のインスタンス変数っぽい。へー。

instance というメソッドも定義されている

rails/activesupport/lib/active_support/inflector/inflections.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

  def self.instance(locale = :en)
    return @__en_instance__ ||= new if locale == :en

    @__instance__[locale] ||= new
  end

:en か それ以外の言語の ActiveSupport::Inflector::Inflections インスタンスを返すのか

それで inflections(locale).plurals

ここで空配列が代入され、

rails/activesupport/lib/active_support/inflector/inflections.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

ここで書かれているように inflect.plural が実行されるみたい。

rails/activesupport/lib/active_support/inflector/inflections.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

@plurals.prepend([rule, replacement]) で配列を返している

rails/activesupport/lib/active_support/inflector/inflections.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

  # 文字列, [[rule, replacement], [...]], locale
  def apply_inflections(word, rules, locale = :en)
    result = word.to_s.dup

    if word.empty? || inflections(locale).uncountables.uncountable?(result)
      # 不可算名詞ならそのまま 文字列を返す
      # information → information
      result
    else
      # word 一部分に最初にマッチした文字列を置換する
      # cat → cats
      # dog → dogs
      # cactus → cacti(irregular)
      rules.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
      result
    end
  end

sub! ってなんだっけ。 「文字列中で pattern にマッチした最初の部分を文字列 replace で置き換えた文字列を生成して返します。」か。

String#sub (Ruby 4.0 リファレンスマニュアル)

Uncountables.uncountable? って何?

rails/activesupport/lib/active_support/inflector/inflections.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

  def uncountable?(str)
    if @pattern.nil?
      # /(equipment|information|rice)/i みたいになるっぽい。わからん...
      members_pattern = Regexp.union(@members.map { |w| /#{Regexp.escape(w)}/i })
      @pattern = /\b#{members_pattern}\Z/i
    end
    @pattern.match?(str)
  end

不可算名詞かどうか判定しているのか。なるほど。

pluralize がの呼び出し元がどこかざっと見てみたが、結構あったのでどこから見ていくか迷い中。 次はここから呼び出し元を追ってみる。

rails/activemodel/lib/active_model/naming.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

ActiveModel::Name が initialize されるタイミングっていつ?

というか ActiveModel::Name って何の責務を持っているクラス?

  > Book.model_name
  =>
  #<ActiveModel::Name:0x0000000122911040
   @collection="books",
   @element="book",
   @human="Book",
   @i18n_key=:book,
   @klass=Book (call 'Book.load_schema' to load schema informations),
   @name="Book",
   @param_key="book",
   @plural="books",
   @route_key="books",
   @singular="book",
   @singular_route_key="book",
   @uncountable=false>

  > Book.model_name.plural
  => "books"

なるほどー。I18npartial、ルーティングとかで使われているのか。

ちなみに ActiveModel::Naming.model_name が Book でも呼び出せるってことは、つまり Book インスタンスでは ActiveModel::Naming module が extend されているってことだろうな。

基本的に継承関係としては User < ApplicationRecord < ActiveRecord::Base になるから、ActiveRecord::Base の中で extend ActiveModel::Naming しているはず...! 見てみたけど、してないな。

rails/activerecord/lib/active_record/base.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

include している中でさらに extend しているのかなー。 include ActiveModel::API が怪しいよね。

見つけた。 included しているから、ActiveRecord::BaseActiveModel::APIinclude されたタイミングで ActiveModel::Namingextend して特異メソッド(クラスメソッド)にしているのかー。

rails/activemodel/lib/active_model/api.rb at 4f328b0a7d57b0213eeea9dd251769b5e7648456 · rails/rails · GitHub

だから、ActiveRecord::Base クラス自体で model_name は呼び出せる状態になっているから、サブクラスの User でも呼び出せるってわけか。 流れは把握できた。

図にしてみる

Book.model_name.plural の流れ

flowchart TD
  A["Book.model_name.plural"] --> B["Book.model_name"]
  B --> C["ActiveModel::Naming#model_name"]
  C --> D{"@_model_nameがキャッシュされているか"}
  D -- "Yes" --> E["キャッシュされたActiveModel::Name を返す"]
  D -- "No" --> F["ActiveModel::Name.new(Book, namespace=nil)"]
  F --> G["ActiveModel::Name#initialize @singular, @plural ... を計算"]
  G --> H["@_model_name に代入"]
  H --> I["ActiveModel::Name を返す"]
  E --> J[".plural を呼ぶ"]
  I --> J
  J --> K["'books'"]

ActiveSupport::Inflector.pluralize(@singular, locale) の流れ

flowchart TD
  B["ActiveSupport::Inflector.pluralize('book', :en)"]
  B --> C["apply_inflections(word, inflections(locale).plurals, locale)"]
  C --> D{"uncountable? or empty?"}
  D -- "Yes" --> E["'book'"]
  D -- "No" --> F["rules を順に試して\nsub! で最初にマッチした変換を適用"]
  F --> G["'books'"]

Kaigi on Rails 2025 参加してきました

Kaigi on Rails2025に参加してきました。その参加レポートです。

1日目

高度なUI/UXこそHotwireで作ろう

speakerdeck.com

所感

Hotwire Anecdota でHotwireについて学びを深めたり、kamalを学ぶ際にzennの記事でお世話になっています。

以前はReactを使用して開発を行なっていたので、「複雑なUI/UXはReactじゃないと作れないよなぁ」という考えだったのですが、今回の発表を聞いて「いや、そんなことないな。なんならHotwireで作った方がjson管理しなくて良いしシンプル作れそう」と考えをアップデートすることができました。確かにjson管理大変だよなぁ。

また、HotwireでのStimulusやTurboがどのような範囲で使用されているのかを解説している資料が分かりやすいので、読んでみてほしいです。

個人的にはReactのone-way data flowをStimulusでも実現しようという考えが面白く、実現したいことはなんとなく見えているのですが、stateの管理がまだイメージできていないです。(value stateとZustandを理解すれば良さそう)

Railsアプリケーション開発者のためのブックガイド

speakerdeck.com

所感

「みんなが同じものを読める」「共有財」として書籍を活用できる。ということを含めて書籍を読んでいなかったので、新しい視点を得られました。

紹介された本は読んだことがあるものから、知っているものまで多くありました。

個人的には最近オブジェクト指向設計について興味を持っているので、「ドメイン駆動設計」や「実践ドメイン駆動設計」を読んで学びを深めようと思います。

Web Componentsで実現する Hotwire とフロントエンドフレームワークの橋渡し

speakerdeck.com

所感

Angular UIコンポーネントWeb Componentsで橋渡しにすることで、Rails Hotwireとして導入することでができることがわかりました。

実際の例を踏まえての解説がとてもわかりやすく、「ユーザー入力を連携するもの」の段階的なアプローチが学びになり、さらにWeb Componentsの理解が深まりました。

今後はReact, VueのUIコンポーネントをWeb Componentsを橋渡しにして実装するのを試してみようと思います。

あなたのWebサービスはAIに自動テストしてもらえる?アクセシビリティツリーで読み解く、AIの『視点』

speakerdeck.com

所感

去年に引き続き、自然言語Capybaraドライバの開発について聞くことができて楽しかったです。

以前はスクリーンショットから入力フォームの位置(座標)を割り出してテストを実行していたことから、最近のBrowser UseやPlaywrite MCPで使用しているアクセシビリティツリーの実装を取り入れることで性能UPしたことに感動しました。

個人的には以前サークルでアクセシビリティに関しての書籍を出したこともあり、アクセシビリティツリーに関しては少し馴染みのあるものでした。音声読み上げツールがサイトのdomをどう解釈するのかを意識することと少し似ているな。と感じました。

Browser UseやPlaywrite MCPの実装を追っていくことで、アクセシビリティツリーに辿り着く過程がすごく痺れました。

Kamalって便利?社内プロジェクト3つをKamal + AWSで運用した体験談

kaigionrails.org

所感

自分が所属しているソニックガーデンの先輩プログラマのyappuさんの発表です。Kamalについては個人的なアプリをデプロイするときに使ったりしたこともあり、できることについては大体把握していました。

しかし、実際にAWS ECSで社内プロジェクトを運用していくにあたり、自動デプロイや名前解決について工夫が必要ということは初めて知りました。

スライドにあったように、デプロイを毎回お願いしていたこともあり、その時を思い出して感慨深くなってしまいました。すごく学びになりました。

かっこよかったです!発表お疲れ様でした!

Railsによる人工的「設計」入門

speakerdeck.com

所感

設計体得できていない状態では、より具体的なコードから考えてしまう。というのはあるあるだと思い、それは設計ではなく「手順」を考えているのでは?ということについてはそうだよなぁと感じました。

今回の発表では設計するということを落とし込み、人工的にメソッドとして「使える」状態まで言語化しており、今の自分に刺さった内容でした。

おそらく、この発表通りの人工的メソッドを丸々使用しても難しい箇所があると思うので、自分なりに試してフレームワークを確立するのがベストかと思いました。

そのために自分が普段どのように設計をしていくのかを1つずつ振り返ることが必要であり、自分なりに論理的に考えられているのかを洗い出していきます。

今改めてServiceクラスについて考える 〜あるRails開発者の10年〜

speakerdeck.com

所感

サービスクラスは使ったことがなく、Fat Modelを避けるための手法として認識していたのがですが、それをチームとしての共通認識として揃えることに関しては割と難しいのだろうな。と感じました。

また、現実的な折衷案としてFormクラスがあるということは知れたのですが、なぜそう考えたのか、という思考まではまだまだ理解できていません。スライドにある通り、DDDやRDB、モジューラモノリスといったことを理解し、なぜそれが必要なのか?ということを自分自身で解釈できないと理解ができないなぁと感じました。

今回の発表を聞き、設計というかRailsのベストプラクティスを自分の頭で考えるために何が必要な要素を知ることができました。

2日目

履歴 on Rails : Bitemporal Data Modelで実現する履歴管理

speakerdeck.com

所感

履歴管理の代表的な手法として、バージョン型と有効期限型が存在することは理解していたのですが、「従業員を起点とした変化」をどう扱うかという視点でパターンを洗い出し、Bitemporal Data ModelをRailsで使えるようにするためにgemを作るのがプログラマとしてカッコ良いな。と思いました。なければ作る姿勢は自分も見習っていきたいです。

また、Bitemporal Data Modelレコードの挙動や、従業員が入社→異動した際の具体的な例まで解説していたところが分かりやすく、説明が入ってきやすかったです。

Sidekiq その前に:Webアプリケーションにおける非同期ジョブ設計原則

speakerdeck.com

所感

長時間リクエストが発生するとプロセス/スレッドが占有されてしまい、サーバが詰まっている状態になる。というWebサーバの仕組みから丁寧に解説していたので、非同期ジョブが必要な背景(理由)がスッと入ってきました。

「それなら大体非同期ジョブでいいじゃないか」という気持ちになるのですが、それだと考慮点が増え、意思決定をすることが増えてしまうという「トレードオフ」が発生するよね。ということから、バッチ処理でもよくない?という提案ができ、非同期ジョブの設計原則・指針を見出すことができる。という流れを分かりやすく解説していて分かりやすかったです。

処理を非同期ジョブにする観点が自分の中で増えたので、今後この設計原則・指針を元に判断していこうと思います。

Introducing ReActionView: A ActionView-Compatible ERB Engine

speakerdeck.com

所感

HerbはErbのParserというイメージだったのですが、FormatterやLinterを行えるようになっていたり(おそらくpreview)と、自分が思っていた以上に強力なライブラリに成長していると感じました。

しかし、それ以上にReActionViewというgemはTemlateView Errorsをかなり分かりやすくしてくれたり、開発者ツールでViews Partials Componentsを表示させ、そこのソースコードを表示することができ、さらに選択した画面に遷移することができるらしく、開発がかなり楽になる予感しかありません。

実際にデモを見た時に会場で「おおおーー!!」という声が上がり、熱気がありました。

今後はStimulus LSPでHTML側からStimulus Controller名を確認できたり、その他いろいろ...(スライド見てみてください)。すごくワクワクして応援したい!と思えるような発表でした。ワクワクしました。

非同期jobをtransaction内で呼ぶなよ!絶対に呼ぶなよ!

speakerdeck.com

所感

非同期ジョブ内で起きるエラーの原因調査が難しい。というあるあるを丁寧に解説していて、transactionがいつDBへのcommitをしているか?非同期ジョブをいつスタートされるのか?を具体例も用いて解説してくれました。

ActiveRecord::RecordNotFoundとActiveJob::DeserializationErrorが起きる原因を特定し、3つの対策を提示してくれました。

自分もハマったことがあるので、「わかる〜」と思って聞いてたのですが、このように何が原因でどのように対策すれば良いのか、までは言語化できていなかったので、今後の開発に生かせそうです!

Rails on SQLite: exciting new ways to cause outages

speakerdeck.com

所感

SQLiteRailsアプリケーションで使用することによる注意すべき点などを話していたんだと認識しています。

個人的にはこのスライドでユーザーごとにファイルを分けるという発想がなかったので、これだとマイグレーション失敗時にはロールバックできるのだろうか?という疑問などが出てきました。実際の発表でどのような観点で話していたのか曖昧なので、動画を見直してみます...。

rails g authenticationから学ぶRails8.0時代の認証

speakerdeck.com

所感

Rails8.0で認証ジェネレーターが追加された背景(理由)から、認証ジェネレーターを使うとどのようなことができるのか?を解説していました。

実際のアプリケーションで認証ジェネレーターを使用する場合にどのような点を考慮すべきか、ということを解説しながら、認証やセキュリティについて学ぶ題材に良い。ということで、ソースコードを追っていきました。

rate_limit, has_secure_password, start_new_session_for, タイミングアタック...という実装と用語について深く理解していなかったので、「知らなくては...」という気持ちになりました。また、認証ジェネレーターで生成されたSessionやCurrentモデルが何をしているのかを把握することで、何をしているのかを大まかに把握することができました。

社内で勉強会開いてみたいな。

Keynote: Building and Deploying Interactive Rails Applications with Falcon

スライド見つからず...

所感

Falcon入れたらめちゃくちゃサーバー負荷が軽減される。ぐらいの理解をしています。gem remove puma gem install falcon のスライドが印象的でした。

今後はpumaではなくfalconが使用されていく事例が増えていくんだろうな。と感じ、次個人で作るRailsアプリケーションはFalconで動かしてみようと思います。

実際にFalconをインストールするデモが面白く、動いているものを見ると自分でも試しちゃいますね。

全体の所感

Kaigi on Rails2024から参加したのですが、以前よりも「確かにな〜」「わかる〜」と思えることが増えてきました。それに伴い「こうした場合はどうなるのだろう?」という自分の意見が少しずつ言語化でき、社内で気になる発表や技術に関してあれこれ議論することができています。

また、去年よりも「設計」というか「概念」など、抽象的な話を理解することができ、自分自身の中でRailsのらしさが少しずつ見えるようになってきたんだと思います。特にServiceクラスについてはかなり考えさせられて、議論が発展していきました。

やはり、現地に行って肌で熱量を感じることが一番の学びになると思っているので、今年も参加できたことを感謝しています。

運営の皆様、登壇者の皆様、行かせてくださった会社の皆様、本当にありがとうございました。

今年のKaigi on Railsも最高でした。

RubyKaigi2025参加レポート

はじめに

愛媛県松山市で開催されたRubyKaigi2025に参加してきました。その参加レポートです。

印象に残ったセッション

Ruby Taught Me About Encoding Under the Hood

speakerdeck.com

@ima1zumiさんの登壇資料です。

初めに、文字コードは歴史的にどのような使い方をされ、どのような変化をしていったのかということを分かりやすく解説していました。 歴史的に調べたことがなかったので好奇心が刺激されました。

そこから、EBCDICに出会い、漢字の文字コードについて苦しめられ、🧑‍🧑‍🧒の不具合に遭遇し、そこからrubyにパッチを当てていくことになり...というような歩みをされていることが分かりました。

自分の周りにはそのような経験をされている方がいないので、驚きながら聞いていました。

🧑‍🧑‍🧒という文字コードirbに貼り付けると余分なスペースが入ってしまい、そこが起因のエラーが発生してしまう。そこを深掘っていくことでrubyを深く知っていく過程を追体験できるような発表でかなり面白かったです。

登壇内容とはずれますが、個人的に気になったこととして、🧑‍🧑‍🧒などの絵文字ってスクリーンリーダーごとに読み上げ方が変わるのかと疑問に思いました。 Unicde Charactor Databaseに文字が当たっているらしいから、この文字を読み上げているのだろうか。深ぼってみようと思います。 https://www.unicode.org/Public/UNIDATA/UnicodeData.txt

Goodbye fat gem 2025

slide.rabbit-shocker.org

@ktouさんの登壇資料です。

概要

  • fat gemとは、ビルド済みのバイナリを含んだgemのこと
  • ネイティブ拡張があるgemはビルドが難しく、ユーザーがつまずきやすい
  • fat gemならその問題を回避できるので、gemを使用するユーザーは使いやすい
  • しかし、そのビルド作業に手間がかかり、gemのメンテナーが対応する状況
  • 開発者の負担が大きく、このエコシステムのままだと辛い。
  • ビルド環境の自動化が進めば、fat gemに頼らない未来(Goodbye)もあるかもしれない

所感

fat gemについては今まで知っておらず、それがあることで開発者がそんなに苦労してるなんて思っていなかったです。

「これが普通」だと思っていたのですが、それは誰かの頑張りの上に成り立ってたんだと改めて感じました。会場ではgemの開発に携わっている方々がいるので尚更です。

便利に使えるのは良いが、その負担が一部の人に偏ってるのは継続的な関係性なのか気になるところでした。 今すぐ自分に何ができるかはわからないけど、現状を知り、少しずつできることを増やしていけたらいいと感じました。

RuboCop: Modularity and AST Insights

speakerdeck.com

@koicさんの登壇資料です。

概要

  • CustomCopの実装で、以前はRubocopの内部構造(例:Inject)に依存する方法を用いていた
  • しかしこの方法は公式に推奨されていないので、内部構図に密結合しないような方法を追加している
  • よって今後はその方法を使用することを推奨している
  • RuboCopでは構文解析の強化として、Prismの導入が進められている

所感

CustomCopを開発する際には、requireで読み込む方法ではなく、pluginsを使用すると良いことが分かりました。

また、自分なりの理解としては、現在はRuboCop自身にLSP機能を内包させるのではなく、Ruby LSPから適切に呼び出されるような仕組みを構築しようとしているフェーズにあるように見えました。

LSPとの連携が進めば、エディタでさらに使いやすくなるので今後の開発が楽しみです。 また、自分でもLSP周辺の実装についてもさらに理解を深めていきたいと思いました。

Ruby's Line Breaks

speakerdeck.com

@spikeolafさんの登壇資料です。

概要

  • Rubyにおける改行の扱いについて、原則と例外を交えて解説されていた
  • そこから、Rubyの文法構造や、オートマトン、LRパーサーの概念について解説されていた
  • 特に、lex stateの複雑さと、それがどのようにパーサーに影響するかが重点的に説明されていた

所感

lex stateがものすごい難しい。ということがわかりました。 それ以外は概念を理解するのに必死で分からなかったです...。去年もこんな感じだったなぁ。

Keeping Secrets: Lessons Learned From Securing GitHub

rubykaigi.org

@lyninxさんと@Creasteryさんの登壇資料です。

概要

  • バグバウンティプログラムを通じて、@Creastery さんによって脆弱性が報告された
  • 脆弱性の内容としては、本番環境のコンテナ内にある環境変数にアクセスされる可能性があったとのこと
  • sendメソッドの特性をうまく利用することで、意図しない形でENVの値を取得できてしまう実装が存在していたらしい

所感

設定情報(config)と機密情報(secrets)を明確に分けて管理すべきという指摘には、確かにそうだなと感じました。基本的にはRails Credentialsを使用するのが良いので、そこをちゃんとすることが大事だと思いました。

また、GitHubのような大規模サービスがRailsを使って構築されている実例を少し見られたのは、個人的に面白く感じました。 今回のケースを通して、セキュリティ対策に関する他のツールを知ることができました。

以下のような静的解析ツールは今後の開発にも役立ちそうなので、試してみたいと思います。

Analyzing Ruby Code in IRB

drive.google.com

@tompngさんの登壇資料です。

概要

  • IRBでは以下のような機能が実装されている
    • 構文ハイライト(syntax highlight)
    • プロンプト文字列の動的制御
    • コードのネスト構造の解析
    • etc...
  • 上記にはRipper::Lexer が利用されているが、IRBに独自パーサーを実装することで機能を実現していた
  • 現在はこの独自パーサーをPrismへ置き換える移行作業が進められており、改善を進めている

所感

スライドにコード例が多く、個人的には理解がすごく進んだと感じました。

普段はIRBを使用してRubyのコードを実行しているのですが、スライドで説明された機能について意識しながら使っていないので、改めて意識すると多くの機能が搭載されている複雑なツールだと感じました。

実際にどのように実装されているのか気になるので、構文ハイライトのコードを読んでいこうと思います。

github.com

RubyKaigiで感じたこと

今年でRubyKaigiへの参加は3回目になりますが、ようやく少しずつ内容が理解できるようになってきた気がしています。セッションを聞いていても、最近のトピックや業界の動きが前よりずっと身近に感じられるようになり、少しずつ自分の中に積み重なってきたものがあるのだと実感しました。

特に印象的だったのは、普段なかなか話す機会のないRubyのコミッターの方々と直接話せたことです。実際にRubyやgemを支えている方と顔を合わせて言葉を交わせる機会というのが貴重で、素晴らしい機会でした。

また、イベントを通して、Rubyという言語を軸に多くの人と出会い、何かしらの縁が生まれる場であることも改めて感じました。こうした技術イベントは、情報収集の場であると同時に、人と人とのつながりを構築するでもあるのだなと感じました。

普段使っているRubyやgem、周辺ツールは「誰かが作ってくれているもの」ではなく、試行錯誤をしながら改善され続けているものだということを肌で感じることができました。自分も何かしらの形で貢献していきたいという気持ちが湧いてきました。

また、Rubyを業務で使うようになってから、RubyKaigiが一段と楽しく感じられるようになりました。仕事と趣味がつながって、より深く技術と向き合える状態になってきているので、そこが自分のモチベーションになってきています。

来年のRubyKaigiに向けて

RubyKaigiを通して、学びや出会いがたくさんありました。 参加するだけでなく、次は何かしら自分も貢献したいと思っています。たとえば、バグ報告やドキュメントの整備、カンファレンスの運営の手伝い、あるいは自分自身でgemを開発してみることなど、関わり方はいろいろあるので、コミュニティに貢献していきたいです。

そのためにも、もっとRubyの理解を深めてイベントやセッションをより楽しめるようになりたいと感じています。知識が増えるほど、見える世界も変わってくると思うので、着実に学びを深めていきます。

まずはKANSAI RubyKaigiにCEPを出すところから始めてみようと思います。 また、英語で技術的なコミュニケーションを取れるようにしたいと思っています。海外の開発者ともスムーズにやりとりできれば、世界がもっと広がりRubyKaigiをもっと楽しめると思っています。

来年の自分が、今年よりも一歩踏み出しているような状態で来年のRubyKaigiに参加したいと思っています。

終わりに

登壇者の皆様、運営者の皆様、スポンサーの皆様方本当にありがとうございました。お祭りのようですごく楽しかったです!!

また、RubyKaigi2025に参加させてくださった会社の皆様方、本当にありがとうございました。

Kaigi on Rails2024に参加してきました

Noboです。愛知県瀬戸市で親方に弟子入りしてプログラマーをしています。

RubyKaigiには2回参加したことはあったのですが、Kaigi on Rails自体には初参加だったのでワクワクでした。

 

会場。立派すぎて入るのに緊張しました。

 

個人的に印象的だった講演

印象的だった発表の感想を書きました。
Ruby, Rails経験が浅いこともあり、異なった解釈があるかと思いますがご了承ください。

Capybara+生成AIでどこまで本当に自然言語のテストを書けるか?

speakerdeck.com

既存のテストではテストシナリオをそのまま実行してしまい、UIが変わった時にテストを変更しないといけなくなり大変という問題がある。

このようなE2Eテストの問題を解消するためには、画面を見て人間っぽくテストしてくれるのが良さそう。という発想から、生成AIに画面を渡してテストしてもらうということを思いついた。
テストシナリオを自然言語にしてやったが、細かい座標が必要で、そこをDOMツリーを渡すことでフォームを入力できた。


フォーム画面のテストをデモで見ることができ、ある程度形になっていることが分かったので、E2Eテストの未来を垣間見ることができました。
テスト速度が遅い、正確なテストができているのか不明。という問題はありますが、そこはいずれ解消できるのはないかと思っています。そうするとRailsバージョンアップ後の画面テストなど、大きな改修があった際にもテストを自然言語で書くことで動作を担保できる時代がきそうだなぁ。と感じてワクワクしました。

 

Cache to Your Advantage: フラグメントキャッシュの基本と応用

drive.google.com

Railsの本体に組み込まれているフラグメントキャッシュについての概要と使い方を説明後、キャッシュ事故を起こさないような対策方法を説明。
フラグメントキャッシュのような一部をキャッシュするのではなく、ページ全てをキャッシュすることができればもっと早くなる発想から、rendering_caching gemを開発している。

 

講演後、登壇者のtkawaさんとお話をして詳細を聞くことができ、より講演内容の理解を深められました。

自分でgemを作ったりできる人は最初から実装の筋道がわかり、それを実装しているのかと思っていたのですが、それは違っており、やりたいことを実現するために試行錯誤していることを肌で感じることができました。

表現が難しいですが、自分も日々「こうできたら良いな」というものを解消するためにgemを作るという選択肢が出てきました。

 

Hotwire光の道とStimulus

 

speakerdeck.com


大原則「制御をサーバに集める」のはなぜか?という疑問を解消するために、HotwireとReactの担当範囲を説明後、実際のStimulusコントローラーの実装について解説していました。

HotwireとReactの違いが分かりやすいスライドでした。
基本的には画面変更をRailsが行い、アプリ独自のイベントハンドリングをStimulusに任せることが理にかなっていることが分かり、それぞれの担当領域が分かったことで、Stimulusを使うタイミングがより明確になったような気がします。

その後、同僚の方お話しさせていただく中で、Stimulusコントローラーの設計は基本汎用的にする方針は分かるが、特定の画面用にStimulusコントローラーを作りたくなるケースも結構あり、その割合が増えれば処理が重複してしまうこともあるので、ケースバイケースだなぁという話を聞けました。そこは実際に経験すると、自分何の考えがモテそうだと思いました。

 

Identifying User Identity

speakerdeck.com

ユーザーのモデリングに関して、もっと細かく分けることでユーザーをの状態を管理することができ、入会→有効化→個人情報の入力→退会というように、ユーザーがアプリケーションに登録するまでのハードルを下げるためには、Deviseが提供しているような設計では難しいことが分かりました。

スライドの最後にあるユーザーの状態をscopeで呼び出せるのは結構かっこいいなぁと感じました。

 

まとめ

Kaigi on Railsは普段業務で使うことの延長線にある講演が多く、理解度が深まりました。「わかる!なるほどなー!」と思いながら講演を聞いていました。


オープニングでRails Way=哲学という話から入り、日々の業務での活用例、失敗例、新たにレールを引こうとしている人、実装の深掘りをしている人...など様々な人が様々なトピックに向き合っているということが分かりました。

また、その内容について同僚や講演している人から直接話を聞き、理解を深められることが現地のイベントに参加する醍醐味だと改めて感じました。

 

Kaigi on Rails2024に参加できて本当に良かったです。

登壇者の皆様、運営者の皆様、スポンサーの皆様方本当にありがとうございました。すごく楽しめました!!

 

また、Kaigi on Railsに参加させてくださった会社の皆様方、本当にありがとうございました。

今年の振り返りと来年の抱負

今年やったこと

プログラミング関連

  • Reactを触った
  • Node.jsを触った
  • Google Cloud Functionを触った
  • コーディングを支える技術を読んだ
  • ゼロからのOS自作入門をやってみた
  • Masterminds of Programmingを読んでみた
  • LTを開催してみた
  • FrontEnd Conference Okinawa2022に参加した
  • JSConf JPに参加した

その他

  • ジムに通い始めた
  • 宅建を受験してみた

今年の感想

仕事

今年はシステムの追加機能、保守やリプレイスで結構大変でしたが、新しい技術を覚えながらできたので凄く楽しくさせていただきました。

しかし、入社して2年目、まだまだできていないことが多いと感じることもありました。

特に改善が必要だなと思う箇所が2点あり

  1. 技術選定

  2. 報連相

1つ目は「なぜ、この技術を使うのか」という問いに納得できる答えを返すことの難しさを改めて知った、という経緯からできていないと感じています。

例えば、モノシリックからマイクロサービスのどちらを選定すべきかという問いの答えはプロダクトの成熟段階や人員、経営事情で変わることもあり、SPA、SSR、SSGやクラウド、テストツールetc...のどれが良いかというという問いもその「状況」を加味しないと答えられず、この「状況」を自分がいる環境に当てはめ、選択可能な手法ができた歴史的経緯を理解し、そこから意思決定をしなければならないと思っています。そうしないと納得のいく説明ができないですからね。

このように、技術選定って考えること多くて凄く大変だ。ということが分かったので、技術選定をしてるチームメンバーを尊敬しています(すげぇ)。と同時に、手法ができた歴史的経緯を理解し、多くの変数を扱う作業は楽しく、やりがいがあるなと思いました。

2つ目は報連相ですね。はい。そりゃ大事ですよね。自分は特に相談するのに時間がかかってしまうというか、色々準備してから相談してしまうので、時間のロスになっているなぁと思う点がいくつかあったので、15分考えて分からなかったらすぐに相談してみようと思います。(誰も分からなかったら、、、気合いで頑張ります)

プライベート

技術書を読んだり、気になるライブラリを使ってみたり、記事を読んでみたりしていました。

技術書ではコーディングを支える技術Masterminds of Programmingが面白かったです。言語の種類やなぜ作られたのか、どのような問題を解決するのか、また、言語の作者のインタビューがあって良かった。

カンファレンスに参加しました。人の発表を聞いたり実際に交流するのは楽しく、勉強になりました。今年は県内だけの参加だったので、来年は県外のカンファレンスにも参加したいなと思っています。

LTを開催しました。自分はイベントを開くこと自体が初めてで、右も左も分からない中イベントの開催をサポートしてくださった方々がいて本当に助かりました。ありがとうございます!また、イベントに参加するよりも開催する方が意外と学びがあるなぁと感じました。とにかく、やってよかったです。来年も開催します!

宅建を受験しました。色々あって受験することにしたのですが、2ヶ月少し勉強して30点ぐらいでした。38点ぐらいが合格ラインだったので、あと1ヶ月頑張ればいけるかなぁ、という感じでした。民法宅建業法は日常生活に直結する知識なので勉強してて楽しかったです。来年は受験するか悩み中です、、。

ジムに入会しました。職場の近くなので業務終了後に行ったりしています。去年は自宅で少しやってたのですが、やっぱりジムは器具が整っていて良いですね。ムキムキになりたい。

来年やってみたいこと

プログラミング関連

その他

  • TOIECを受験してみる(英語話せるようになりたいな)
  • 宅建再受験?
  • 県外のカンファレンスに参加する(RubyKaigi?)
  • ベンチプレス100kg上げたい

抱負

去年は目標を立てはような記憶があるのですが、記録が見当たらないので、今年はちゃんと記録して、1年後に「全部できたぜー!やったー!」と喜びたいので、コツコツと頑張っていきたいと思います。

タスク管理にはNotionを使います!Notion最強!ちょっとした記録にはObsidianを使います。

今年関わってくれた皆様、今年もお世話になりました。来年もよろしくお願いします!

The Super Tiny Compilerを写経してみた

はじめに

この記事はCODE BASE OKINAWA Advent Calendar 2022の21日目の記事になります。

1年ほど前に「言語処理系ってどうなっているんだろうな〜」と漠然と疑問に思っていて、Rubyで作る奇妙なプログラミング言語を一通りやったのですが、ほぼ内容を忘れていたので、今回たまたま見つけたThe Super Tiny Compilerをやってみることにしました。

The Super Tiny Compilerとは

Javascriptで書かれたコンパイラのこと。

github.com

Lispっぽい呼び出しをCっぽい呼び出しに変換します。

2 + (4 - 2) → (add 2 (subtract 4 2)) → add(2, subtract(4, 2))

全体の流れ

  1. Token生成(TOKENIZER)
  2. 構文解析(PARSER)
  3. AST変換(TRAVERSER)
  4. 新AST変換(TRANSFORMER)
  5. コード生成(CODE GENERATOR)

解説

解説を書こうと思ったのですが、凄く分かりやすくまとめている記事を発見したので、ぜひ読んでほしいです!めちゃ分かりやすい。

TypeScript with Denoで実装しているしリポジトリもあるから、後で写経してみよかな、、!

感想

ソースコードよりもコメントが多くてびっくり。その分丁寧に解説が書かれていたので一連の処理がイメージしやすかったのがとても良かったです。 また、Javascriptで書かれ、コード量も少ないのでそこまで時間がかからずにでき、とっかかりとして優れた教材だと思います。

個人的はAST→新ASTに変換(TRANSFORMER)の実装が難しかったです。parent._context_という意味が分からなかったり、parentってどういう意味だっけ?と何度も動かして確認していました。多分?理解できていると思います。

別の言語で実装してみるのもいいかもしれないです。ちなみにRubyはありました。

次はGoで作るインタプリタをやってみようかと思います。 Rubyで作るRubyも良さそう。

www.oreilly.co.jp

RubyでつくるRuby ゼロから学びなおすプログラミング言語入門www.lambdanote.com

Web Speech APIを使ってみた

どうもノボです。プログラムを書いたりしてます。
最近Web Speech APIを触ってみる機会があったので、ちょっとしたメモアプリを作ってます。

 

このアプリを参考にしています。(こんなのができたらいいなぁ、、
https://efcl.info/2022/02/10/voicod/

 

作ったものはこちらになります。(デプロイはまだです、、
https://github.com/Hitoshi-Noborikawa/memo-app

 

Web Speech APIとは?

Web Speech API音声認識音声合成をブラウザ上で使用することができます。https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API
デモはこちらhttps://github.com/mdn/web-speech-api

 

使い方

ローカルで立ち上げてください。dockerを使っています。

Startボタンを押すと音声認識が始まります。何か話すと読み込まれます。

f:id:Nobox:20220221215710p:plain

話してみた

OKボタンを押すと、上のテキストエリアに表示されます。

f:id:Nobox:20220221215536p:plain

上に表示

,を入力すると、が文末に追加され、.を入力すると文末に。が追加され、改行されます。

f:id:Nobox:20220221215956p:plain

,と.を入力してみる

 OKを押すとこんな感じになります。

f:id:Nobox:20220221220224p:plain

改行されました

今は少しの機能しかありませんが、メモアプリとしてメモを保存できたりファイル分けしたりサードパーティーと連携したりできたらいいなと思ってます。(デザインも頑張ります、、!

 

今回はこれで。読んでくれてありがとうございます。