crowdworks.jp エンジニアの佐々木です。
株式会社クラウドワークスは,2026年4月22日から26日にかけて北海道函館市で開催された RubyKaigi 2026にプラチナスポンサーとして協賛し,企業ブースを出展しました。
当該ブースにおいては,Rubyに関連する体験型クイズアプリケーションを提供し,開催期間中の3日間で延べ148名の参加者を得るに至りました。この場を借りて,厚く御礼申し上げます。
本アプリケーションでは,主にRubyのメソッドにおける実行結果を問う問題を出題しました。参加者からは,未知のメソッドに対する知見の深化を評価する声が寄せられた一方,アプリケーションの設計や開発工程についても高い関心が示されました。
本稿では,当該アプリケーションの開発プロセスを詳述するとともに,クイズの解答データの集計値や特に正答率の低かった5つの設問についての解説を行います。
アプリケーションの開発
開発環境の選定
本アプリケーションの開発にあたっては,限られた準備期間内での運用効率と開発スピードを最優先事項とし,プラットフォームとしてGoogle Apps Script(GAS)を採用しました。
選定にあたっては,以下の3つの評価軸を定義し,その妥当性を検証しました。
インフラ構築および運用コストの極小化
大規模な環境整備や専用サーバーの契約を要さず,また金銭的な付随コストを発生させずに迅速なデプロイが可能であるか機能要件の充足
ユーザーからの入力受領,入力値の記録,動的な画面表示,および解答プロセスの時間計測といった一連の機能を単一の環境で完結できるか可搬性と運用容易性
オンライン環境下において,標準的なWebブラウザを搭載した端末1台で実行・管理が可能であり,イベント会場での運用適性が十分であるか
また,開発着手前の段階で策定していた具体的な機能要件は,以下のとおりでした。
- インターフェース: 直感的な操作を可能にする多肢選択形式
- データ管理: 設問,選択肢,および正誤判定基準をExcelまたはGoogleスプレッドシート上で一元管理
- 出題アルゴリズム: セッション開始時に,プールされた数十問の設問からランダムに1問ずつ呈示
- フロー制御: 正答時は即座に次問へ遷移し,誤答時は正答を呈示するフィードバック工程を経て次問へ遷移
- リアルタイム統計: 設問ごとの累積解答数と正答数を逐次記録し,設問呈示と同時に最新の正答率を表示
- データ運用の効率化: 解答データおよび統計値を設問管理と同一のシート内で完結
これらの諸条件を総合的に勘案した結果,Googleスプレッドシートをデータベースとして活用し,Webアプリケーションとして柔軟な実装が可能なGASが最も合理的な選択肢であると判断するに至りました。
アプリケーションの実装
アプリケーションの実装にあたり,生成AI(Gemini)に対して技術的助言を求めました。具体的には,前述の要件を概略的な仕様としてGeminiに提示し,基盤となるソースコードの初案を出力させました。この出力を起点とし,以下に示す手続きを反復的に実行することで,実装の洗練と機能の拡充を図りました。
基本ロジックの自動生成
設問のランダム抽出およびGoogleスプレッドシートとの連携といった,GASにおける中核的なロジックの構築実運用に即した詳細の修正・追加
誤答時のフィードバック表示の視認性向上や,多重入力の防止,レイアウトの調整といった項目について,AIへの追加指示と手動でのコード改訂継続的なリファクタリング
動作確認の過程で生じた細かな不備や,より高度なユーザー体験を実現するための機能追加を段階的に実施
設問作成
本アプリケーションの核となる設問の作成にあたっては,RubyKaigiという技術習熟度が極めて高い層が集うことを考慮し,単なる文法知識の確認に留まらず,「エンジニアの知的好奇心を刺激し,新たな発見があること」を基本方針としました。
具体的な設問の策定手続きは以下のとおりです。
テーマの抽出と候補リストの構築
Rubyの言語仕様におけるエッジケースや,一見すると予想に反する挙動を示すメソッド,または最新のRubyにおける変更点などを中心に候補となるテーマを抽出。特に,日常的な開発では意識されにくいRubyの深淵に触れる内容をGeminiを活用して優先的にリストアップ設問の選別と仕様の確定
リストアップされた候補に対し,「詳細な補足説明を要さず,問題文のみで完結すること」や「記述式解答において入力内容が一意に定まること」を基準として選定難易度区分の定義とキャリブレーション
作成された設問群を,Geminiの提案および作成者の主観的感覚に基づき「易・中・難」へと分類検証とリファクタリング
すべての設問について,実際のRuby環境での動作確認を実施
最終的に,これらの中から選別した51問を設問プールとして採用し,さらに以下のアルゴリズムに基づき計6問を呈示する設計としました。
- 選択式設問(3問): 難易度区分「易」「中」「難」から各1問をランダムに呈示
- 記述式設問(2問): 難易度区分「易」「難」から各1問をランダムに呈示
- 最終設問(1問): 「おまけ問題」として最後に呈示
完成画面例
本インターフェースの設計にあたっては,「RubyKaigi」という技術カンファレンスの特性を考慮して,参加者であるエンジニアにとって親和性の高い視覚的演出を施しました。具体的には,多くの開発者が日常的に利用するコードエディタを彷彿とさせるダークテーマのデザインを採用しました。また,クイズの正誤判定および実行結果の表示においては,Rubyにおける標準的なテストフレームワークである「RSpec」の出力結果を模した表現を取り入れました。このような遊び心を交えた技術的な意匠を随所に盛り込むことで,RubyKaigiという場に相応しいユーザー体験の提供を試みました(図1a–d)。
図1a ロード画面
図1b 出題・解答画面
図1c 正答時画面
図1d 誤答時画面
クイズの結果
先述のとおり,今回提供したクイズアプリケーションは,全51問の設問プールを備え,以下のアルゴリズムに基づき計6問を呈示する設計でした。
- 選択式設問(3問): 難易度区分「易」「中」「難」から各1問をランダムに呈示
- 記述式設問(2問): 難易度区分「易」「難」から各1問をランダムに呈示
- 最終設問(1問): 「おまけ問題」として最後に呈示
最終設問については開発当初の想定を大幅に上回る難易度となったため,運営側によるヒントの提示や外部情報の参照(Web検索等)を前提とした解答となりました。
ここでは,正答数,解答に要した時間,正答率を算出しました。なお,統計値の表記にあたっては,特筆しない限り,データの散らばりを考慮し「平均値 ± 1標準偏差」の形式を採用しています。
正答数
平均正答数は3.31 ± 1.34問でした。正答数の分布は以下のとおりです(表1)。なお,構成比は有効数字が3桁となるように四捨五入しています。
| 正答数(問) | 人数(人) | 構成比(%) |
|---|---|---|
| 6(全問正解) | 4 | 2.70 |
| 5 | 31 | 20.9 |
| 4 | 29 | 19.6 |
| 3 | 41 | 27.7 |
| 2 | 31 | 20.9 |
| 1 | 10 | 6.76 |
| 0 | 2 | 1.35 |
| 合計 | 148 | 100 |
余談ですが,今回の正答率の分布は正規分布に従っているとは言えないものでした。最終問題の解答や全体の難易度設定が影響したのかもしれません。
解答に要した時間
平均解答時間は141 ± 75.3秒でした。全問正解者の最速解答時間は34.7秒でした。解答時間の分布は以下のとおりです(表2)。なお,構成比は有効数字が3桁となるように四捨五入しています。
| 解答時間(秒) | 人数(人) | 構成比(%) |
|---|---|---|
| 0–50 | 5 | 3.38 |
| 50–100 | 38 | 25.7 |
| 100–150 | 58 | 39.2 |
| 150–200 | 22 | 14.9 |
| 200–250 | 13 | 8.78 |
| 250–300 | 6 | 4.05 |
| 300 < | 6 | 4.05 |
| 合計 | 148 | 100 |
正答率
クイズ全体の平均正答率は58.4 ± 26.4%でした。各カテゴリにおける正答率は以下のとおりです(表3)。なお,最終問題については上記の理由のため,正答率の計算からは除外しています。
| 出題形式 | 難易度 | 平均正答率(%) |
|---|---|---|
| 選択式 | 易 | 63.7 ± 31.5 |
| 中 | 60.7 ± 23.1 | |
| 難 | 51.5 ± 22.4 | |
| 記述式 | 易 | 70.2 ± 24.8 |
| 難 | 45.7 ± 26.7 | |
| 全体 | 58.4 ± 26.4 |
難問解説
ここでは,最終問題を除く正答率下位1–5位の問題について解説します。
1. (:a..:z).step(26).to_a.last
(記述式,難,正答率5.88%)
正解は :a です。
まず,(:a..:z) によってシンボル :a から :z までの範囲を定義するRangeオブジェクトを作成します。ラテンアルファベットの総数は26文字です。
次に適用されている step(n) メソッドは,範囲内の初項から開始し,指定された増分nごとに要素を抽出します。本設問ではn = 26であるため,初項 :a の次項は26個先の要素となります。しかしながら,当該範囲の終端は初項から25個先の :z であり,その次項は定義範囲外に位置します。結果として,step(26) で取り出されるものは :a のみとなります。
続く to_a メソッドによって,抽出された要素を格納した配列 [:a] が生成されます。
最後に last メソッドが適用されることで,当該配列の末尾要素である :a が戻り値として出力されます。
2. "10" + 5
(選択式,易,正答率8.33%)
選択肢: "15",15,TypeError,"105"
正解は TypeError です。
Stringクラスにおける + 演算子は,右辺のオペランドとしてString型のインスタンスを要求します。Rubyの言語仕様においては,IntegerからStringへの暗黙的な型変換は実行されません。したがって,異なるデータ型を直接連結しようとした場合,型不一致に起因する TypeError が発生します。
3. [1].repeated_permutation(3).to_a.size
(記述式,難,正答率14.3%)
正解は 1 です。
まず,レシーバとなる要素数1の配列 [1] に対して,repeated_permutation(n) メソッドを適用します。当該メソッドは,レシーバの要素を重複して選択することを許容し,指定された長さnの組み合わせを列挙します。本ケースにおいては,選択可能な要素は 1 のみであるため, 組み合わせは [1, 1, 1] の1通りに確定します。
続く to_a メソッドにより,列挙された組み合わせを要素とする配列が生成されるため,結果は [[1, 1, 1]] となります。
最後に,当該配列に対して size メソッドを適用し,格納されている要素数を計上することで,1 が出力されます。
4. 42.singleton_class
(選択式,難,正答率19.0%)
選択肢: #<Class:#<Integer:0x...>>,Integer,TypeError,Numeric
正解は TypeError です。
singleton_class メソッドは,レシーバとなるオブジェクトの特異クラスを返し,当該クラスが存在しない場合は動的な生成を試みます。ただし,Integer,Float,およびSymbolクラスのインスタンスについては,Rubyの内部実装において即値(immediate value)として表現されており,特異クラスを保持するためのオブジェクト実体を持ちません。したがって,これらの型に対して特異メソッドの定義や特異クラスの参照を試みた場合,言語仕様上の制約に基づき TypeError が発生します。
5. String.ancestors.include?(Enumerable)
(選択式,中,正答率20.0%)
選択肢: true,false,nil,NoMethodError
正解は false です。
Ruby 1.9系における言語仕様の刷新に伴い,StringクラスはEnumerableモジュールの包含を廃止した仕様へと変更されました。
アンケート結果
クイズに参加された方には,普段最もよく使用している言語は何かというアンケートにも回答していただきました。
RubyKaigiの来場者が対象だったこともあり,回答の大部分をRubyが占める結果となりました。主要な回答としては,Rubyに次いでJavaScript, Go, Pythonの順に高い割合を記録しました(図2)。
自由記述(その他)においては,次のような多岐にわたる言語およびフレームワーク等が報告されました: C, Dart, dbt, Emacs Lisp, Java, Koka, Kotlin, MySQL, Next.js, PHP, Rust, Swift, Terraform, TypeScript, Vim script
図2 メイン言語のアンケート結果(N = 147)
終わりに
RubyKaigi 2026の期間中,弊社ブースにお立ち寄りいただき,また本クイズに参加することでRubyの奥深さを共に楽しんでくださった全ての皆様に心より感謝申し上げます。本クイズアプリケーションの開発および分析から得られた知見,そして皆様との貴重な交流を糧に,今後もRubyコミュニティのさらなる発展に微力ながら貢献してまいります。
結びに代えまして,当日「おまけ問題」として会場の空気を和ませた(あるいは,ある意味で技術クイズ以上の難問となった)設問をここに再掲し,本稿を締めくくりたいと存じます。
Question: クラウドワークスのマスコットキャラクターの名前は何?