[GSoC Proposal Draft] - Anuj Pal - Extension System (Railtie Equivalent) #237
Replies: 2 comments 7 replies
-
|
Hi @anuj-pal27 This is a very strong and well-researched proposal! One minor comment: instead of building a dummy extension, I highly recommend picking a real, popular Ruby gem (e.g., Sentry SDK or Datadog SDK) and writing an actual Rage extension for it as your final deliverable. This will prove the system works for real-world use cases and allow you to polish the implementation. |
Beta Was this translation helpful? Give feedback.
-
|
Hey @rsamoilov , thank you so much for taking the time to review and share such detailed feedback — it really helped me improve the proposal. I've addressed all the points you mentioned. Whenever you get some free time, please do take a look! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
1. Contact Information
2. What project do you want to work on?
I want to work on the Extension System for Rage under rage-rb/rage. I found this project on the ideas list and reached out to the mentors @daz-codes and @cuneyter to discuss it further. The idea of building something foundational — a system that other gem authors will build on top of — is what drew me to it.
3. Why do you like Ruby, and why do you want to work on a Ruby project in GSoC?
I started with Ruby through Rails during a backend mentorship, and what struck me immediately was how expressive and readable the code is. Ruby feels like you are writing what you mean, not fighting the language to say it. I got curious about how Rails itself works under the hood — Railties, the boot process, middleware stacks — and that curiosity is what eventually led me to Rage.
I want to work on a Ruby project in GSoC because the Ruby open source community is genuinely collaborative. The maintainers take time to review and discuss ideas, not just merge PRs. That kind of environment is where I learn the most.
4. Describe your experience with Ruby, C, and other languages
5. Educational Background
B.Tech in Computer Science Engineering at RBS Engineering Technical Campus, Agra (2022–2026), currently in my 4th year with a CGPA of 8.13.
Alongside my degree, I completed a year-long Ruby on Rails internship under the mentorship of a senior backend developer in ROR at Security Compass, where I got hands-on experience building real backend features in a production Rails environment. No prior degrees or publications.
6. Pull Requests to Ruby Open Source Projects
rage-rb/rage (Rage framework)
[Rendering] Custom renderer support #244 — Merged ✅
Implements the
config.renderer(:name) { ... }DSL. Registers custom rendererblocks and generates
render_<name>methods onRageController::APIat boot time.Add singular resource routing and specs #247 — Open
Implements the singular resource route helper in the router DSL and updates
the spec suite to validate all supported options and behaviors.
hostedgpt (Ruby on Rails) — https://github.com/AllYourBot/hostedgpt
Rage — POC for the Extension System
I have been actively contributing to Rage itself.
7. Other Commitments This Summer
I do not have any major commitments during the GSoC period. I have kept this summer free specifically to focus on GSoC. I can comfortably commit the full 40 hours per week.
8. Vacations or Trips This Summer
No trips or vacations planned during the GSoC period.
9. Classes This Summer
I will not be taking any classes during the GSoC coding period.
10. Other Employment This Summer
No other employment this summer. GSoC will be my primary focus.
11. Previous GSoC Participation
I applied to GSoC once before but was not selected — I was not prepared enough at the time and did not have a strong proposal or prior open source contributions. Since then I have building real projects with Rails, and investing time in understanding codebases deeply before proposing changes. This application is the result of that preparation.
12. Project Proposal
Please see the full proposal below.
Project: rage-rb/rage
Mentors: @daz-codes, @cuneyter
Contributor: Anuj Pal
Project Size: ~175 hours
Difficulty: Medium
1. Short Introduction
Hi, I'm Anuj, a Backend developer in Ruby on Rails. Currently in 4th year of my college. I came across Rage while looking for Ruby frameworks to contribute to, and the Extension System project immediately caught my attention.
I have been exploring how Rails solves this problem through Railties, reading the Rails source code, and building a small POC inside a real Rage app to understand the problem better. You can find my POC here:
https://github.com/anuj-pal27/Rage_Railtie_POC
2. Problem Understanding
Right now, if someone wants to integrate a third-party gem with Rage, they have to do all the setup manually in their app. There is no standard way for a gem to say "when Rage boots, run my setup code automatically."
For example, if someone wants to add error tracking with Sentry, they have to manually initialise it, configure it, and hook it into the right place themselves. This is extra work for every developer using that gem, and it is easy to get wrong.
Rails solved this problem a long time ago with Railties. A gem can inherit from Rails::Railtie, define its setup code inside lifecycle hooks like before_configuration or after_initialize, and Rails runs it automatically during boot. The developer using the gem does not have to do anything extra.
Rage does not have this yet. As Rage grows and more gems want to support it, this becomes a real problem. Without a standard extension system, every gem will solve it differently, or not at all.
3. Technical Approach
High-level Architecture
The extension system will have four main parts:
1.
Rage::ExtensionBase ClassThis is the class that any gem inherits from to plug into Rage. As soon as a gem inherits from it, Rage automatically knows about it — no manual registration needed.
This works because of Ruby's
inheritedhook:2. Where Hooks Plug Into Rage's Boot Process
I read through
lib/rage/setup.rbto find exactly where the hooks need to be inserted. Here is how the current Rage boot sequence looks and where the extension hooks will be added:This means user config always wins — extensions set defaults in
before_configuration, and the user overrides them inRage.configure. The order is guaranteed.3. Lifecycle Hook Points
before_configurationRage.configureblockinitializer "name"after_initializeEach hook is stored as a proc and run in registration order:
4. Named Initializers
Internally stored as an ordered list of
{ name:, block: }pairs — the name makes it easy to debug which initializer failed during boot:5. Configuration Namespaces
Each extension needs its own config namespace without Rage knowing about it in advance. To ensure
config.my_gemworks alongside existing namespaces likeconfig.server,config.loggeretc., I'll extendRage::Configurationitself.The extension system will register a namespace accessor that lazily creates a nested config object when accessed — keeping everything under the same
configobject and avoiding parallel configuration trees.So extensions can set their own defaults:
And users override in
Rage.configure:This preserves all current config behavior while safely adding extension namespaces. User config always wins because
Rage.configureruns afterbefore_configuration.6. Execution Order — What Happens With Multiple Extensions?
When two or more gems register the same hook, they run in the order they were loaded — same as Rails. This is predictable and easy to reason about:
7. Edge Cases I Have Thought About
What if an extension raises during boot?
Named initializers wrap their execution in a rescue block and re-raise with the initializer name included, so the developer knows exactly which extension failed.
What if config is accessed before
before_configurationruns?ExtensionConfigusesmethod_missingto lazily create namespaces, so accessingconfig.my_gembefore it is set just returns an emptyExtensionConfigobject rather than raising aNoMethodError.What if two extensions set the same config key?
Last write wins — same as Rails. The user's
Rage.configureblock always runs last, so user config is never overwritten by an extension.8. Before vs After — The Developer Experience
Without the extension system today:
With the extension system:
Everything else — middleware injection, tracing setup, backtrace cleaning — happens automatically. Zero manual wiring.
9. Full API Reference
10. Rake Task Support
After reading through both
lib/rage/tasks.rband Rails' Railtie source, I found that Rage already loads rake tasks fromlib/tasks/**/*.rakeinsideRage::Tasks.init. But there is no way for a gem to register its own rake tasks into that system yet.The fix is straightforward — extensions register a block, and
Rage::Tasks.initruns all registered blocks before loading app tasks:
Internally in
Rage::Extension:And a one line change in
Rage::Tasks.init:This is a small, focused change that fits naturally into what Rage already does. Generators are a different story — Rage does not have a generator system yet so that needs more groundwork and is better left for V2.
4. Milestones & Timeline
Total: ~175 hours over 10 weeks
Week 1 — Codebase Familiarization & Final Design
The design is already largely shaped through pre-GSoC research — reading through
lib/rage/setup.rb, studying Rails Railtie, building the POC, and discussing with mentors. Week 1 will be used to finalize any remaining design decisions,get mentor sign-off on the API, and set up the development environment properly before writing any production code.
Week 2–3 — Core Extension System
Build the
Rage::Extensionbase class with auto-registration using Ruby'sinheritedhook. This is the foundation everything else builds on. Write tests as I go.Week 4 — Lifecycle Hook Points
Add all three hook points into Rage's boot process:
before_configuration— runs before app config loadsinitializer— runs after user config, before app bootsafter_initialize— runs after app fully bootsWrite tests for each hook point to make sure they fire in the right order.
Week 5 — Named Initializers
Add named initializer support with proper error handling — if an initializer raises, the error message includes the initializer name so the developer knows exactly what failed during boot.
Week 6–7 — Configuration Namespaces
Extend Rage's existing configuration to support dynamic extension namespaces. Handle edge cases like config conflicts and make sure user config always overrides extension defaults.
Week 8 — Middleware & Rake Task Support
Allow extensions to inject middleware into Rage's stack inside
after_initialize. Also add rake task support by hooking intoRage::Tasks.init— extensions can register task blocks that load alongside the app's own rake tasks.Week 9–10 — Sentry SDK Extension & Final Testing
Build a real Rage extension for the Sentry SDK as the final deliverable — covering middleware injection, config namespaces, named initializers, and backtrace cleanup. Fix any remaining issues, write documentation for gem authors, and submit the final work.
5. Deliverables
6. Real World Validation — Sentry SDK Extension
To prove the system works against a real-world gem, the final deliverable will be a Rage extension for the Sentry SDK. I studied how Sentry's existing Rails integration works through
Sentry::Railtieand mapped each part to what Rage needs.Sentry Scope
I'll be explicit about what is being ported from Sentry's Railtie.
setup_backtrace_cleanup_callbackandactivate_tracingwill be defined inside the Rage extension itself, not assumed to exist elsewhere.In scope (ported / implemented):
Sentry.initsetup using user configSentry::Rack::CaptureExceptions)setup_backtrace_cleanup_callback) — defined in the extensionactivate_tracing) — defined in the extensionOut of scope for V1 (to be explored later):
These exclusions will be clearly documented in both the proposal and code comments so the scope is unambiguous.
How Sentry currently boots in Rails:
How the same will work in Rage:
Reference: https://github.com/getsentry/sentry-ruby/blob/master/sentry-rails/lib/sentry/rails/railtie.rb
After reading through Sentry's existing Rails Railtie, I mapped out what actually matters for Rage. Here's what I came up with:
Looking forward to working closely with the mentors to ship something the Rage ecosystem can build on for years.
Beta Was this translation helpful? Give feedback.
All reactions