Summarized using AI

The Rails Features We Loved, Lost, and Laughed At

Robby Russell • July 08, 2025 • Philadelphia, PA • Talk

Introduction

In "The Rails Features We Loved, Lost, and Laughed At" presented by Robby Russell at RailsConf 2025, the history and evolution of the Ruby on Rails framework are explored through a journey across its most impactful, forgotten, and amusing features. The speaker details how Rails’ philosophy, innovations, and experiments have shaped both the framework and the broader developer community over two decades.

Key Points

  • Early Rails Magic and Philosophy:

    • Rails brought structure, rapid feedback, and productivity, allowing developers to scaffold models, validate data, and set relationships quickly.
    • Emphasized "convention over configuration," enabling developers to focus on building features instead of boilerplate setup.
    • Active Record stood out as an iconic feature, streamlining database interactions compared to contemporaneous frameworks.
    • The Rails console provided direct application introspection, minimizing development friction.
    • Rails introduced versioned database migrations, test generation, and helpful view helpers, encouraging good practices and enjoyable development.
  • Features That Faded Out:

    • Some features, while innovative, proved less robust or suitable as applications and teams grew:
    • ActiveResource: Sought to treat remote APIs like local models, but struggled with third-party inconsistencies; later abandoned in favor of bespoke HTTP clients.
    • ActiveRecord Observers: Aimed for cleaner callback handling but led to debugging challenges and was ultimately removed.
    • Page and Action Caching: Provided early static HTML caching but became brittle and obsolete with more dynamic apps.
    • Dynamic Scaffolding: Instantly generated CRUD interfaces at runtime but lacked customization, leading to its removal.
    • attr_accessible: Controlled mass assignment but was replaced by strong parameters for better clarity and safety as application complexity increased.
  • Playful and Whimsical Features:

    • Rails experimented with user delight and "magic," including:
    • RJS templates for generating JavaScript with Ruby, simplifying AJAX-heavy functionality.
    • Syntactic sugars like button_to and link_to_function for interactive UIs.
    • Early JavaScript helpers such as observe_field and the Scriptaculous library for dynamic effects.
    • Dynamic finders and even semicolon-delimited actions, which, while interesting, often led to clutter or confusion, and were removed or downplayed as Rails matured.
  • Recurring and Refined Ideas:

    • Some concepts re-emerged in improved forms, such as:
    • Turbo, which draws on legacy ideas to achieve interactive front-ends with minimal JavaScript by leveraging modern browser APIs and HTML.
    • The evolution from multiple form helpers towards a unified, intuitive form_with, streamlining developer experience.
  • Community and Lasting Impact:

    • The talk used anecdotes, such as the Amtrak train story to the first RailsConf, to illustrate the momentum and camaraderie within the Rails community.
    • Rails’ willingness to learn, iterate, and sometimes retire features is highlighted as a unique strength, fostering lasting joy and productivity.

Conclusion

Robby Russell reflects that the legacy of Rails lies not just in its technical features, but in the community’s capacity to adapt, experiment, and return to old ideas with fresh perspectives. The framework’s real achievement is its focus on reducing friction and maximizing the joy of building applications, ensuring relevance through thoughtful iteration and clear values.

The Rails Features We Loved, Lost, and Laughed At
Robby Russell • Philadelphia, PA • Talk

Date: July 08, 2025
Published: July 23, 2025
Announced: unknown

Rails has always moved fast. Sometimes too fast. It gave us bold ideas, best practices that weren't, and features that felt like magic – until they didn't.

Before database migrations, SQL changes were a manual mess. Before REST, routing conventions were a free-for-all. Before AJAX, entire pages refreshed just to update a single field. Some features transformed how we build apps. Others were left at the station. A few refuse to stay gone.

This session takes a fast-paced, slightly irreverent ride through the features that shaped Rails, the ones we hyped up only to abandon, and the ones that just won't quit. Rails keeps moving forward, but history has a way of repeating itself. Let's see what we can learn from the features we built, broke, and buried.

Some ideas never left the station. Others keep coming back for another ride. See you onboard. 🚂

RailsConf 2025

00:00:16.800 We were somewhere near Montana on Amtrak
00:00:19.439 when the caffeine began to take hold.
00:00:21.359 The sun was rising, the Wi-Fi was
00:00:23.439 non-existent, and someone had just
00:00:25.439 managed to boot a Rails app at 75 mph.
00:00:29.279 16 of us, laptops open, Rails apps
00:00:32.160 booting in a moving train car in route
00:00:34.160 to the very first Rails comp and we were
00:00:37.120 all in on this new framework. But we'll
00:00:39.440 come back to this ride later. Today I'm
00:00:41.200 going to take you on a little bit of a
00:00:42.160 trip. So Rails has been around for over
00:00:44.079 21 years now and in that time it's
00:00:46.160 introduced a lot of features. Some we
00:00:48.079 still use to this day, some we've
00:00:49.920 forgotten about, some maybe we wish we
00:00:51.520 could forget about. But together they
00:00:53.280 tell a story not just of the framework
00:00:55.199 but of the community behind it. Rails
00:00:57.760 has always moved fast. It's held strong
00:01:00.000 opinions. It has bold defaults and has
00:01:02.640 made the occasional curious detour.
00:01:05.439 Today, we're going to take a ride
00:01:06.400 through some of that history. Today,
00:01:08.400 we'll make a few stops along the way.
00:01:10.159 Some will feel familiar. Others might
00:01:12.080 bring back some memories, but this isn't
00:01:13.760 about pointing fingers or poking fun.
00:01:15.840 It's about understanding how Rails has
00:01:17.520 evolved and how it's helped us evolve as
00:01:19.759 developers, too. So, here's how this is
00:01:21.759 going to work. I'm going to take us
00:01:23.200 through a handful of stops, moments in
00:01:25.360 Rails histories that mark big ideas, big
00:01:27.600 swings, or maybe just some big
00:01:29.200 personalities.
00:01:30.720 Some features we still love, some we
00:01:32.880 quietly extracted. And some newer
00:01:35.439 developers stumble across in our
00:01:36.799 codebases like they're artifacts from a
00:01:38.880 forgotten civilization.
00:01:40.880 And in the spirit of Rails itself, we'll
00:01:42.799 keep moving. So grab your bags and hop
00:01:44.960 on board. We're headed back where things
00:01:47.119 started clicking. a time when Rails gave
00:01:48.880 us structure, momentum, and maybe even a
00:01:51.759 little bit of magic. So, let's roll into
00:01:54.079 stop one where we jumped on board.
00:01:57.119 This was a This is where Rails hooked
00:01:58.880 us. You could scaffold the model,
00:02:01.520 validate some user input, set up a few
00:02:03.680 relationships, and run your test all in
00:02:06.000 the first hour or 15 minutes if you were
00:02:07.680 making a blog. The defaults were smart,
00:02:10.160 the opinions were helpful, and the
00:02:11.920 feedback loop was lightning quick. It
00:02:14.160 felt like the framework truly wanted us
00:02:16.239 to succeed.
00:02:17.680 Now, these features didn't just save us
00:02:19.120 time. They made building joyful.
00:02:22.000 Now, one of Rails's biggest
00:02:23.599 contributions wasn't a method or a
00:02:26.480 class. It was a philosophy.
00:02:41.040 You didn't need a giant XML file to
00:02:42.959 explain where your uh models or
00:02:44.720 controllers live and you just built your
00:02:46.160 app and it worked. That shift saved us
00:02:49.280 from so much boiler plate and let us
00:02:51.200 focus on building features, not on
00:02:52.959 wiring things together. Now, active
00:02:55.680 record is arguably the most iconic piece
00:02:57.840 of Rails. The name itself comes from
00:02:59.840 Martin Fowler's book, Patterns of
00:03:01.280 Enterprise Application Architecture. But
00:03:02.720 in Rails, it wasn't just a pattern. It
00:03:04.800 was the default way of getting
00:03:06.000 done. With active record, you could
00:03:08.080 write user.post and you weren't thinking
00:03:09.680 about foreign keys or join tables. You
00:03:12.879 were thinking about what your user
00:03:13.920 wanted to connect to. It made your data
00:03:16.000 feel live, not just some mysterious data
00:03:19.040 stored in a hash cache in the cloud.
00:03:21.200 Now, I feel like I should provide some
00:03:23.519 context for what developers were
00:03:25.040 navigating during this era. For example,
00:03:27.200 if you're using Java or M Hibernate
00:03:29.440 around this time, here's kind of a
00:03:30.640 highle overview of what would go into
00:03:32.720 that. Disclaimer, these are my best
00:03:35.120 examples I can find from the 2004 era of
00:03:37.280 hibernate. But here's an equivalent of a
00:03:39.440 domain object say in hibernate for say
00:03:41.280 an article. You got your you define your
00:03:43.760 getters, your setters, you could have a
00:03:45.440 title body, author, and then there's
00:03:48.159 this thing called a hibernate mapping
00:03:49.599 XML file which is where you'd map your
00:03:52.319 Java class files to corresponding
00:03:54.000 database columns. This is where you
00:03:56.239 define one to many or many to one
00:03:58.400 relationships.
00:04:00.000 Then to interact with this in your app,
00:04:02.239 uh you'd then use these setters and
00:04:04.239 you'd save your data in the database.
00:04:06.400 Now you might be thinking that doesn't
00:04:07.680 actually look all that bad, right? It's
00:04:09.120 only like four or five lines of code.
00:04:10.879 But what happened if it didn't actually
00:04:12.560 successfully save? For example, if you
00:04:15.280 had a unique constraint on an article,
00:04:17.840 you need to handle the types of
00:04:19.040 exceptions and any other data
00:04:20.560 validations. We needed to write quite a
00:04:22.880 bit of code for that business logic. And
00:04:25.360 then one day, active record arrived.
00:04:28.560 We didn't need needed to define all
00:04:29.759 those getters and setters. No
00:04:31.120 configuration. We could just toss in a
00:04:33.280 few validations and in a few lines of
00:04:35.360 Ruby code. We were confident adhering to
00:04:37.520 our application's business logic without
00:04:39.680 needing to wire up very much. Less
00:04:41.919 boilerplate, less ceremony, more joy.
00:04:44.960 Active record wasn't just simpler, it
00:04:47.280 felt human because Rails invited us to
00:04:49.360 write code that spoke clearly about what
00:04:52.080 we wanted it to achieve.
00:04:54.560 In my opinion, Rails console might be
00:04:56.160 one of the most quietly powerful tools
00:04:58.560 in the whole framework. You could poke
00:05:00.400 around your app, run queries, debug some
00:05:02.800 weirdness, no browser needed, no break
00:05:05.040 points, no scaffolding a controller just
00:05:06.800 to test something out. And when things
00:05:08.639 went sideway in production, it was there
00:05:10.160 for you, too. We can investigate issues
00:05:12.639 on our servers, log in, fix a data issue
00:05:15.520 without having to redeploy our
00:05:16.800 application. That shrunk the feedback
00:05:19.039 loop. It built up our confidence in
00:05:20.800 understanding how this Ruby and Rails
00:05:22.479 thing all kind of worked at the time.
00:05:24.560 Now, before Rails, managing database
00:05:26.800 meant editing a bunch of SQL files,
00:05:28.479 typically writing altered table
00:05:29.840 statements, saving them in a shared
00:05:31.919 folder, maybe emailing them around with
00:05:33.440 your co-workers. You never really knew
00:05:35.039 if a change had been run in production
00:05:37.440 yet. It was a very clunky era of
00:05:40.720 database management. We push changes
00:05:42.720 production or schema changes was clunky.
00:05:44.639 And if you were working with the DBA,
00:05:46.240 you probably had a pretty slow review
00:05:47.600 loop too. Rollbacks if you were lucky.
00:05:50.720 Active record integrations changed all
00:05:52.400 that. Now schema changes were versioned
00:05:54.800 and lived in our source control and you
00:05:57.039 can run them with just one command and
00:05:58.560 this built up our confidence that the
00:05:59.840 local and production environment schemas
00:06:01.680 were kind of aligned. Now Rails didn't
00:06:04.080 just support testing, it kind of
00:06:05.440 expected it. When you generated a model,
00:06:07.680 it created a test file and a fixtures.
00:06:10.319 No setup, no configuration, just some
00:06:12.160 encouragement that helped establish a
00:06:14.479 habit. Teams started writing tests
00:06:16.720 earlier and more often. And once testing
00:06:19.360 became more normal, we had some
00:06:21.199 cognitive bandwidth and started
00:06:22.400 imagining maybe some new ways of
00:06:24.160 thinking about testing and that led to
00:06:25.360 things like RSpec and BDD whether you
00:06:27.280 like them or not. But Rails never forced
00:06:29.520 you to write tests. It just made it
00:06:31.199 really easy to get started.
00:06:33.600 Provi Rails provided us with a bunch of
00:06:35.120 helpers that quietly made our apps feel
00:06:37.440 polished requiring very little effort on
00:06:39.759 our parts. You didn't need to write a
00:06:41.120 bunch of custom logic for string
00:06:42.639 truncation, currency formatting,
00:06:45.039 thinking about pluralization. For
00:06:46.800 example, in PHP around this era, it
00:06:48.720 wasn't horrible. You could probably make
00:06:50.080 a function for this or something, but it
00:06:51.520 was kind of quite verbose to handle
00:06:53.039 things like that. And then contrast that
00:06:54.880 with Rails, these small little
00:06:57.039 conveniences added up. They cleaned up
00:06:58.880 our views. They made our apps more
00:07:00.400 consistent. And they made it easier for
00:07:02.080 teams to read and maintain each other's
00:07:03.919 codebase and gave me kind of a business
00:07:05.440 model. Now, one of the most thoughtful
00:07:07.440 parts of Rails has always been how it's
00:07:09.440 helped us speak to our users. Use error.
00:07:13.039 messages gives us friendly human
00:07:15.919 readable validation messages without
00:07:18.319 requiring us to write a bunch of if
00:07:19.840 field blank add error then if error
00:07:22.479 display error just built into the stack
00:07:25.280 and that flash hash it gave us a
00:07:27.759 built-in way to communicate success and
00:07:29.520 information and failures between
00:07:30.880 requests helpers weren't flashy but they
00:07:34.000 saved us time simplified our views and
00:07:36.800 again helped us create much better user
00:07:38.479 experiences with such little effort on
00:07:40.479 our part
00:07:42.240 rails gave us a lot of thoughtful tools
00:07:44.160 early on. A lot of those things still
00:07:46.240 exist to this. All of those things still
00:07:48.160 exist and it doesn't look that much
00:07:49.360 different. But these things made
00:07:51.759 building web apps feel joyful and fast.
00:07:54.960 But not every feature stuck around. Some
00:07:56.960 are experiments, some didn't age well,
00:07:59.360 and some just didn't work out the way
00:08:00.560 that we hoped they would.
00:08:03.280 Welcome to the quietest stuff. This is
00:08:05.599 where Rails features arrive with
00:08:07.039 purpose. sometimes even with fanfare,
00:08:10.400 but over time they prove to maybe not be
00:08:12.319 quite the right fit. Some we've quietly
00:08:14.400 extracted or maybe they've faded from
00:08:16.160 memory. Who here remembers active
00:08:18.800 resource?
00:08:20.960 Let me see your hands. Who used active
00:08:23.039 resource in production?
00:08:25.199 Okay, who's still using active record in
00:08:27.039 production?
00:08:29.919 Active res resource. Okay, one. Okay,
00:08:33.360 thank you.
00:08:35.839 So active resource was ambitious. This
00:08:38.080 was a Rails attempt to make one app talk
00:08:39.760 to another over HTTP. Not a super novel
00:08:42.479 idea in in the modern time, but treating
00:08:44.880 basically a remote API like it was an
00:08:46.560 active record model. In theory, it was
00:08:48.080 beautiful. You could just write invoice
00:08:49.760 fine and Rails would make a rest call
00:08:51.360 under the hood. It worked quite nicely
00:08:55.519 when we owned our own APIs. Active
00:08:58.399 record or active resource let us pretend
00:09:01.279 that we had a distributed active record.
00:09:03.360 But in the real world, other people are
00:09:05.519 hell and other people's APIs aren't
00:09:06.959 quite so polite. They rate limit you.
00:09:09.120 They return weird error messages and
00:09:10.720 they change their formats midweek.
00:09:12.480 Things go up flip upside down. And
00:09:15.120 eventually was like Rails was like,
00:09:16.480 you're probably going to want to handle
00:09:17.360 this yourself. Today, we lean on things
00:09:19.120 like Faraday or HTTP party to build our
00:09:22.000 own API clients for our Rails apps.
00:09:25.600 Active record observers allowed us to
00:09:27.920 extract all these side effect callbacks
00:09:30.480 from our models and move them into some
00:09:32.560 other class.
00:09:34.320 It sounded cleaner for a while,
00:09:36.080 especially, for example, if you had like
00:09:37.600 an invoice and you wanted to sync it to
00:09:39.120 QuickBooks, but you didn't want the
00:09:40.240 invoice model to really know that
00:09:41.600 QuickBooks existed. You could do that.
00:09:43.600 You could have multiple observers
00:09:44.959 observing the same model. Got a little
00:09:46.959 crazy. You could save a record, update
00:09:49.040 records records, and something else
00:09:51.120 would happen somewhere else. But but
00:09:52.880 where you'd have to re-reference your
00:09:55.279 environment files to figure out which
00:09:57.200 ones were loaded and which environment
00:09:59.120 what order they were being loaded in
00:10:01.040 practice was a little implicit maybe not
00:10:03.279 widely used or understood difficult to
00:10:05.680 debug and it fell out of favor was
00:10:07.760 extracted in Rails 4. Page and action
00:10:10.720 caching were early attempts to speed up
00:10:12.640 our Rails apps by skipping the
00:10:14.000 controller entirely. Fastest Rails app
00:10:16.800 is no Rails app I think. Um for example,
00:10:19.519 we might want to cache our articles. So
00:10:21.519 we'd call caches page in our controller
00:10:24.160 and with page caching, Rails would write
00:10:26.560 the full HTML to the public directory on
00:10:29.120 our app servers. So then there would be
00:10:30.720 HTML file and then on a subsequent
00:10:32.800 request, Apache or EngineX would then
00:10:34.880 serve that file without needing to hit
00:10:37.120 Rails. It was fast. It was also brittle.
00:10:39.760 If one partial changed, you had to
00:10:41.519 expire the whole page or manually delete
00:10:43.440 files in your servers. A lot of us had
00:10:45.279 multiple app servers. So we had a lot of
00:10:47.040 HTML files that were regularly trying to
00:10:49.040 delete and keep cleaned and figuring out
00:10:50.560 where the cache was broken. This is
00:10:52.640 before we had tools like memcache or
00:10:54.399 Reddus readily available. So Rails did
00:10:57.040 what it could with the file system. But
00:10:58.640 our apps got a little bit more dynamic.
00:11:00.399 The approach didn't quite hold up so
00:11:01.680 well. These caching features were
00:11:03.360 extracted and now we might look at using
00:11:04.880 things like Russian doll caching in
00:11:07.120 Reddus or solid cache. Early Rails had
00:11:10.160 something called dynamic scaffolding.
00:11:11.600 You just drop in scaffold invoices, no
00:11:13.760 files, no views. Rails would just
00:11:16.000 autogenerate the credit interface at
00:11:17.519 runtime. It was magical or maybe a cool
00:11:20.800 parlor trick until because because
00:11:24.240 until you needed to change something, it
00:11:25.920 was a little tricky because you had
00:11:27.440 there was nothing actually changed
00:11:28.720 because it was automatically generated
00:11:30.160 in real time. So, Rails tended to also
00:11:42.079 gave us adder accessible to protect
00:11:43.600 against mass attribute assignment. You'd
00:11:45.839 whitelist which attributes could be
00:11:47.600 updated and where. For example, let's
00:11:49.279 say you had editorial workflow where
00:11:51.279 writers could draft an article, but only
00:11:53.360 an editor could publish it. So, we use
00:11:55.440 adder accessible and our models for each
00:11:57.040 role and our controllers. you'd have to
00:11:58.959 pass that role context when we'd call
00:12:01.360 active record um to save our records and
00:12:04.000 stuff like that. It was simple but our
00:12:06.079 apps tended to get a little more
00:12:07.040 complicated and a lot of teams were
00:12:08.399 growing and so suddenly tracking which
00:12:10.240 fields were being used exposed and where
00:12:12.480 got a little confusing and so in Rails 4
00:12:14.800 we got strong parameters and moved that
00:12:16.480 logic into the controller where it was
00:12:18.959 arguably easier to see and manage. Some
00:12:21.360 folks didn't love this change at the
00:12:22.720 time because it was challenging the
00:12:24.480 skinny controller fat model mindset, but
00:12:27.200 I think it was a thoughtful mind
00:12:28.959 thoughtful shift. It's more explicit,
00:12:30.880 more transparent, and a little safer for
00:12:33.040 teams that are growing quickly. Now,
00:12:35.040 these weren't failures. These were
00:12:36.639 experiments. Rails trying to abstract,
00:12:38.880 to simplify, to be clever. But at our
00:12:41.519 next stop, Rails gets a little bit more
00:12:43.200 playful.
00:12:46.320 This is the stretch of track where Rails
00:12:48.160 got even whimsical.
00:12:52.399 Because it wasn't just about
00:12:53.279 productivity, it was about delighting
00:12:55.040 ourselves, at least if anyone. Helpers
00:12:57.120 that dance, features that felt like
00:12:58.880 magic spells, clever, curious ideas that
00:13:01.600 made us pause and smile. Some of these
00:13:03.839 features were genuinely helpful when
00:13:05.839 they came out. Others made things a
00:13:07.360 little harder to understand in long run,
00:13:09.200 but the but at the time they felt like
00:13:10.720 it was one of our secret weapons.
00:13:13.600 There was this time in Rails when we
00:13:15.120 wrote JavaScript with Ruby. With RJS
00:13:17.920 templates, your controllers would
00:13:18.959 respond by rendering Ruby that would
00:13:20.720 then output JavaScript. The important
00:13:22.560 part was that we weren't writing
00:13:24.480 JavaScript. You're just asking Rails to
00:13:26.560 write it for you. Um,
00:13:31.760 we also had features like button to and
00:13:33.519 link to function. You weren't linking to
00:13:35.839 a URL. You were linking to a JavaScript
00:13:37.760 function. It was fast. It felt powerful
00:13:40.079 at the time and it worked on most
00:13:41.680 browsers and except for maybe some IE
00:13:44.160 situations. But as our apps grew, our
00:13:46.800 view started to get kind of messy. We
00:13:48.880 also had observe field which made our
00:13:51.040 apps feel futuristic, at least for 2006
00:13:53.440 era. We used it for live search,
00:13:55.600 autocomplete, tagging, you name it. For
00:13:58.079 example, let's say we had a text field
00:14:00.240 and we wanted to watch for user input
00:14:02.000 every half second or so. That would fire
00:14:04.079 off an Ajax request to a controller. We
00:14:06.880 could have that return a partial to
00:14:08.399 render in our search results. No SPA
00:14:10.720 needed. We had no build tooling, no gem
00:14:12.880 files. This was all vanilla Rails. You
00:14:15.120 could do all this. We loved that power.
00:14:17.120 And we eventually also learned how to
00:14:18.959 let things go once we as a community
00:14:21.120 started to embrace unobtrusive
00:14:22.480 JavaScript. Scriptaculus
00:14:25.519 brought us animations and visual effects
00:14:27.760 to our early Rails apps that made it us
00:14:29.839 feel so powerful. You could build
00:14:31.839 shopping carts with literal drag and
00:14:33.519 drop functionality. I remember being at
00:14:35.199 a conference and seeing someone
00:14:36.560 literally dragging a t-shirt into a
00:14:38.160 shopping cart. I'm like, we all need
00:14:40.079 that. That's like that's the future of
00:14:42.480 buying on the internet is dragging to
00:14:44.639 the thing instead of clicking add to
00:14:46.720 cart.
00:14:48.560 It's funny how things kind of reverb.
00:14:50.639 Anyways,
00:14:52.240 for a while this was pure, you know,
00:14:54.480 crack cocaine for us backend developers
00:14:56.720 that were getting a little crazy with
00:14:58.160 our JavaScript, but it was there. But as
00:15:02.000 JavaScript, as a JavaScript ecosystem
00:15:04.000 evolved, Rails decided to step back.
00:15:06.639 These effects weren't removed from being
00:15:08.800 included with Rails because they were
00:15:10.160 bad or anything. They just didn't need
00:15:12.000 to be bundled by default anymore.
00:15:15.680 We're always waiting on JavaScript
00:15:18.079 things to this is that was 2006. All
00:15:20.880 right. One of the early early Rails
00:15:23.440 superpowers was you could just write
00:15:25.199 invoice. Customer code and underscore
00:15:27.680 number and it would just magically work.
00:15:30.240 These were called dynamic finders,
00:15:32.160 method names that would turn into these
00:15:33.600 queries for you. You didn't have to
00:15:35.120 write the SQL which was what we were
00:15:36.720 trying to avoid as much as we could. You
00:15:38.639 didn't need to configure anything but
00:15:40.399 method name started to get kind of long
00:15:42.399 started wrapping and our queries tended
00:15:44.399 to get a little more complicated than
00:15:45.600 this. It's probably Rails doing a little
00:15:47.839 bit too much behind the curtain. So we
00:15:49.680 stepped back. Now we have explicit find
00:15:51.680 by wear conditions and use name scopes.
00:15:54.240 At the time Rails was giving us
00:15:55.600 something easy to reach for to keep it
00:15:57.680 readable. But as you can see we were
00:15:59.199 also very verbose with our attribute
00:16:00.720 names. So it made these method names
00:16:02.160 really freaking long.
00:16:04.240 And here's one you might not believe,
00:16:06.079 but Rails briefly supported semicolon
00:16:08.240 delimited actions. What the does
00:16:10.399 that mean? Like SLbooks ID
00:16:13.199 semicolonedit.
00:16:14.720 This is this approach was inspired by
00:16:16.480 the Java server specs, something called
00:16:18.959 matrix parameters.
00:16:21.040 The idea is super simple. All right. So
00:16:23.600 each segment of a URL path could carry
00:16:26.560 its own metadata. Got it? You
00:16:29.680 understand? Was that make sense? Anyone
00:16:32.079 know how to read that? All right, Rails
00:16:34.399 didn't go this deep with it, but this
00:16:36.240 isn't the Java uh Java server specs. Uh
00:16:39.600 we had this in what Rails 1.1 and 1.2.
00:16:42.480 It basically let us insert these
00:16:43.759 semicolons in our routes to call custom
00:16:45.279 actions that didn't quite fit cleanly
00:16:47.519 into REST. And the idea was to
00:16:50.160 discourage RPC style actions. I'm just
00:16:52.320 re reading verbatim what I read on some
00:16:54.079 track post. Um track SBN was our old
00:16:58.000 Rails uh place to deal with issues back
00:17:01.199 then. Also, you can't find that stuff
00:17:03.040 and left out using the internet archive.
00:17:04.799 So, thankful that that exists. But this
00:17:07.039 confused a lot of devs like myself.
00:17:09.199 Broken Safari and we're quietly
00:17:11.439 extracted in Rails 2.0. As DH said at
00:17:14.880 the time, just not worth it. So, Rails
00:17:17.520 quietly let it go and we just embraced
00:17:19.439 the forward slash.
00:17:21.439 Rails gave us some strange, delightful,
00:17:23.199 and unusually clever ideas. They weren't
00:17:25.039 always perfect, but they sparked
00:17:27.199 curiosity and they left a mark. and
00:17:29.840 Rails, it doesn't forget. Some ideas
00:17:32.160 just need some time to come back around
00:17:33.919 because not everything in Rails is about
00:17:35.440 forward motion. Some of the most
00:17:37.360 interesting ideas in the framework are
00:17:39.039 the ones we've circled back to, refined,
00:17:41.760 renamed, and reimagined. These are the
00:17:44.240 loops, the moments where Rails said,
00:17:46.720 "Maybe we weren't wrong, we were just
00:17:49.120 weren't ready, or where the community
00:17:51.280 asked for a second or third time to try
00:17:53.120 something better."
00:17:55.039 Turbo is the latest stop in Rails's long
00:17:57.280 tradition of asking, can we make the
00:17:58.960 front end easier without going all in on
00:18:00.880 JavaScript? We've been trying to avoid
00:18:02.080 JavaScript forever. We've seen this
00:18:04.240 before. Remote true, unobtrusive
00:18:06.160 JavaScript, observed field. Turbo builds
00:18:08.799 on all those ideas, but with cleaner
00:18:10.400 structure, modern browser APIs, and a
00:18:12.720 bit more staying power. We hope it lets
00:18:15.440 us build fast interactive experiences
00:18:17.120 using mostly HTML, which is great,
00:18:19.039 especially for teams that want to say as
00:18:20.720 much as they can in the Rails mindset.
00:18:23.600 This is not Rails ignoring JavaScript
00:18:25.360 though. It's Rails simply saying HTML
00:18:28.320 might still be enough.
00:18:30.880 And this is the most important
00:18:32.160 refactoring I think of all time in
00:18:33.520 Rails. For a long time, we had form 4
00:18:35.840 and form tag and they worked, but they
00:18:38.480 also forced us to explain things like to
00:18:41.360 the junior dev. Well, this one's for
00:18:43.280 models. This one's not unless you pass
00:18:46.559 it a URL and then it sort of is super
00:18:49.280 easy. So even eventually Rails said
00:18:51.679 let's make this easier. So we got form
00:18:54.000 with one helper consistent behavior not
00:18:57.280 because the old way was broken but
00:18:58.880 because Rails keeps revisiting its
00:19:00.880 decisions and sometime sometimes the
00:19:03.200 kindest thing that we can do for our
00:19:04.720 future selves and developers is to
00:19:06.880 reduce friction and whenever we have an
00:19:08.960 opportunity to do so. Now when I first
00:19:11.600 pitched this talk I thought I'd be
00:19:13.120 digging through a trough of Rails
00:19:15.200 features that we could all be laughing
00:19:16.640 here about. you know, semicolon roots,
00:19:19.280 RJS, axis, hasslehoff. But the more I
00:19:22.320 look back, the more I realized that we
00:19:24.799 were never laughing at the code. We were
00:19:26.880 laughing with each other because Rails
00:19:29.360 took care of the hard stuff, the boiler
00:19:31.679 plate, the wiring. And that meant that
00:19:34.480 we had more mental space to think about
00:19:36.960 the product, to care about the user
00:19:39.520 experience, to argue about button copy
00:19:43.120 instead of database schemas. Rails
00:19:45.760 didn't just make us more productive. It
00:19:48.320 made us feel like we could build
00:19:49.919 anything. And it attracted people who
00:19:52.080 wanted to move fast, who cared about the
00:19:54.240 bigger picture, not just the code, but
00:19:56.400 what the code could do for us. So before
00:19:58.880 we roll into this immemoriam, it's the
00:20:01.280 second one of the day, I think. Let's
00:20:02.559 remember these features weren't just
00:20:03.919 tools. They were our momentum. Cue the
00:20:06.559 music.
00:20:12.559 Let's take a quiet moment to remember
00:20:14.080 the features that once lived in our
00:20:15.440 Rails apps. Some were brilliant,
00:20:21.600 some were brief, but all of them meant
00:20:24.160 well.
00:20:56.240 They may be gone from the framework, but
00:20:58.400 they live on in our git history,
00:21:02.159 in outdated blog posts,
00:21:04.799 and in the hearts of developers stuck
00:21:07.280 maintaining 2011 error code bases. May
00:21:10.320 they rest on rubygeems.org.
00:21:16.480 These weren't failures. They're
00:21:18.080 reminders that Rails is alive and always
00:21:21.039 learning.
00:21:28.400 Ideas return when the time is right. And
00:21:30.320 when they do, they come back lighter,
00:21:32.320 cleaner, and better shape for the world
00:21:34.320 that we're building in now. Remember
00:21:38.240 that train ride I mentioned? In 2006,
00:21:41.679 16 of us boarded the Amtrak in Portland,
00:21:44.000 Oregon, and took it to Chicago,
00:21:45.360 Illinois. A 48 hour ride to the very
00:21:48.640 first Rails Comp. No Wi-Fi, no iPhones
00:21:52.320 existed, no Git, no access to download
00:21:55.360 Ruby gems, only whatever we had saved in
00:21:57.760 our vendor folder, just laptop, script
00:22:00.559 server, console demos, and a cooler full
00:22:03.120 of questionable beverages.
00:22:05.760 But more than that, we had momentum, a
00:22:08.559 shared sense that something was about to
00:22:10.720 take off. And look at that kid.
00:22:16.320 Don't do it.
00:22:18.880 So, here we are at our final stop. But
00:22:20.880 if you've been on the Rails train for
00:22:22.400 any amount of time, you know there's no
00:22:23.600 true last stop because Rails keeps
00:22:25.520 moving. Not just adding, but editing.
00:22:29.120 Not just new ideas, better ones. This
00:22:32.240 whole ride we've been on, it's not been
00:22:34.159 about the features. It's been about how
00:22:35.360 Rails learns. Rails doesn't just move
00:22:37.679 forward. It loops. It reflects. It
00:22:39.520 circles back. Not out of nostalgia, but
00:22:41.679 with clear eyes. And that's rare. Most
00:22:44.480 frameworks chase trends. Rails asks,
00:22:46.799 "Where's the friction? And how can we
00:22:48.799 make it feel effortless again? Because
00:22:50.559 that's where the joy lives." And every
00:22:52.559 few years, something we thought was
00:22:54.320 essential starts to feel unnecessary.
00:22:57.600 A tool that used to save us time, now
00:22:59.919 it's slowing us down. a pattern that
00:23:02.159 seems so elegant now it's hard to
00:23:04.400 explain to the new hire. Rails has
00:23:06.720 taught us that these good defaults often
00:23:09.120 come from hardearned lessons. So the
00:23:11.919 question is what are we clinging on to
00:23:14.320 today that we're going to be laughing
00:23:16.000 about fondly in 5 years.
00:23:19.840 Rails doesn't need to be cool again. It
00:23:22.080 needs to be clear. Clear about what it
00:23:24.159 values. Clear about who it's for. And
00:23:26.799 clear that the joy of building isn't a
00:23:29.039 phase. It's the point.
00:23:32.080 Thank you.
00:23:34.480 If you've enjoyed the ride, please
00:23:35.919 remember to tip your conductor or at
00:23:38.799 least leave a good commit message.
00:23:40.559 Thanks for writing along with me today.
00:23:42.080 If you have any questions or want to
00:23:43.200 come say hi, come please see me around
00:23:44.960 the conference. And remember, it's okay
00:23:46.559 to laugh at your old code just as long
00:23:48.320 as you keep writing new code. Worth
00:23:49.600 laughing about someday. And before I
00:23:51.760 step off the stage, one last thing. I've
00:23:54.480 been collaborating with the Rails
00:23:55.440 Foundation on a new podcast. It's called
00:23:57.200 On Rails. We had one episode out with
00:23:59.039 Rosa that came out a week or two ago.
00:24:01.120 It's not about the hype or news. It's
00:24:03.039 about the real stuff. How teams actually
00:24:04.960 build, adapt, and keep their production
00:24:06.720 Rails apps running smoothly. This sounds
00:24:09.440 like your thing, I hope you give it a
00:24:10.559 listen. Thanks again.
Explore all talks recorded at RailsConf 2025
Manu Janardhanan
Christopher "Aji" Slater
Hartley McGuire
Yasuo Honda
Ben Sheldon
Chad Fowler
John Athayde
Mike Perham
+77