Summarized using AI

10 Years of Roda

Jeremy Evans • November 15, 2024 • Chicago, IL • Talk

Summary of "10 Years of Roda" Presentation

In this presentation at RubyConf 2024, Jeremy Evans discusses the evolution of Roda, a Ruby web toolkit, over the last decade since its launch in 2014. He highlights Roda's unique advantages, technical advancements, and its successful application in various open-source projects.

Key Points Discussed:

  • Introduction to Roda: Roda integrates routing directly with request handling, which simplifies web application development significantly compared to other Ruby frameworks.

  • Technical Advantages:

    • Request Handling During Routing: Unlike many other frameworks, Roda allows for request processing during the routing phase, which can reduce complexity and improve performance.
    • Performance Metrics: Roda consistently outperforms its competitors in terms of request processing speed and memory usage. Jeremy provides benchmarks indicating that Roda can handle high numbers of routes efficiently.
  • Plugin System:

    • Roda has a small core that relies on a rich plugin ecosystem to extend its functionality. The toolkit has grown from 15 initial plugins to over 120, catering to diverse web application needs.
    • Plugins can be added or omitted as required, which helps enhance both performance and usability based on application demands.
  • Reliability Features: Roda implements immutability to reduce potential memory leaks and improve thread safety. It also employs namespace pollution control to prevent conflicts with user-defined methods and constants, making applications more robust.

  • Development History: Roda’s consistent release schedule has introduced numerous optimizations and features, leading to significant performance improvements, with particular advancements made in handling matching and request processing efficiency over the years.

  • Case Studies:

    • KFA Web: This is a front-end application utilizing Roda that manages asset serving based on gem versioning, reducing duplication in routing logic.
    • UB Cloud: A startup developing an open-source alternative to AWS, utilizing Roda’s routing and authentication capabilities to manage both browser-based and API requests efficiently.

Conclusion and Takeaways:

  • Roda not only simplifies the building of web applications but also provides a scalable and reliable solution characterized by high performance and low resource consumption.
  • The toolkit has reached over 10 million downloads and continues to evolve, with ongoing support from developers who are committed to its advancement. Those interested in reducing cloud costs or deploying Ruby applications can benefit from exploring Roda further.

Jeremy concludes by inviting the audience to engage with the UB Cloud team for related queries, reinforcing the community's role in fostering continued development and application of Roda.

10 Years of Roda
Jeremy Evans • November 15, 2024 • Chicago, IL • Talk

Roda is a Ruby web toolkit that uses a routing tree. It integrates routing with request handling, which significantly simplifies the development of web applications. Roda has a small core and an extensive plugin system, which has allowed it to add many features while significantly increasing performance.

The first conference presentation on Roda was given 10 years ago at RubyConf 2014. Come learn about Roda, the progress Roda has made since then, how Roda powers open source frameworks and applications, and why you may want to use Roda for your next web application.

RubyConf 2024

00:00:15.240 all right so I'm super happy to be here
00:00:16.400 at Ruby comp to talk about Roa so Roda
00:00:19.119 is a web toolkit that I launched in
00:00:21.600 2014 I had the pleasure of presenting
00:00:23.840 the newly launched Roa at Ruby conf 14
00:00:26.279 2014 and it's great to be back at Ruby
00:00:28.519 conf 10 years later to discuss roa's
00:00:30.960 progress so in this presentation I'll be
00:00:33.360 going over the advantages of using Roa
00:00:35.920 uh discussing the progress made in the
00:00:37.480 last 10 years since launch and looking
00:00:40.079 at how some open-source software uses
00:00:42.039 Roa my name is Jeremy Evans I maintain
00:00:44.800 Roa and many other rubby gems I'm also a
00:00:47.360 ruby committer who focuses on fixing
00:00:49.120 bugs in Ruby additionally I'm the author
00:00:51.559 of polished Ruby programming a book
00:00:53.399 aimed at intermediate Ruby programmers
00:00:56.320 so before discussing the first 10 years
00:00:58.320 of Roa I'm going to dive into a simple
00:01:00.879 Roa example in case you were not
00:01:02.840 familiar with it and while a little bit
00:01:05.080 more complex than hello world this
00:01:07.000 example shows R's key advantage over
00:01:09.119 other Ruby web Frameworks which is the
00:01:11.119 ability to handle requests during
00:01:12.960 routing instead of separating the
00:01:14.880 routing process from the request
00:01:17.000 handling process so with Roa all
00:01:19.960 requests to the application are yielded
00:01:22.320 to the route block and the route block
00:01:24.479 is responsible for handling all requests
00:01:27.320 by convention Ro uses r as the rout rout
00:01:30.079 block variable at any point in the route
00:01:32.680 block you can do processing related to
00:01:34.600 the request for example if you want to
00:01:36.680 check access by IP you could have that
00:01:38.960 check at the top of the route block and
00:01:41.399 this would be the equivalent of an
00:01:42.880 application Level before hook in other
00:01:45.280 Frameworks now assuming we pass the
00:01:47.320 access check we get to the first routing
00:01:49.280 method so the r.on method is used to
00:01:51.680 handle branches in the routing treat in
00:01:55.119 this example the r.on method is passed
00:01:57.200 two arguments called matchers and the
00:01:59.960 first is the string employee which will
00:02:02.399 match if the next segment in the request
00:02:05.039 path is
00:02:06.360 employee and the second is a class
00:02:08.280 integer which will match if the next
00:02:10.080 segment in the ring path is an integer
00:02:12.879 so if you look at the combination of
00:02:14.680 these two matchers they will match
00:02:16.800 request path such as SL employee sl7 and
00:02:20.080 since the entire request path has been
00:02:21.920 consumed by the matchers the remaining
00:02:24.160 path is empty the matchers will also
00:02:27.000 match requests such as/ employee sl7
00:02:30.000 slash name and the remaining path after
00:02:32.760 this would be slash name which is what
00:02:35.160 routing methods inside the block would
00:02:37.480 operate on it would not match a path
00:02:40.080 such as SL vendor sl9 since the first
00:02:42.760 segment is not employee and it would
00:02:45.440 also not match a path such as SL
00:02:47.840 employee slame because name is not an
00:02:51.120 integer now if the request does not
00:02:53.280 match the r.on call r.on will return nil
00:02:56.760 without yielding to the block and in
00:02:59.319 this example it would reach the end of
00:03:00.879 the route block resulting in a 404
00:03:03.519 response because the request was never
00:03:06.680 handled the request does match the art
00:03:09.040 on call it will yield to the provided
00:03:11.319 block and because the integer class
00:03:13.840 matcher was used the block would be
00:03:16.000 yielded that segment of the request path
00:03:18.799 converted to an integer so for a get
00:03:21.319 request for SL employee sl7 name the
00:03:24.879 employee ID block variable would be the
00:03:27.080 integer 7 now inside the block the first
00:03:29.959 line is this code which shows the
00:03:32.080 primary advantage of Rota which is at
00:03:34.480 any point during routing you can do
00:03:36.920 processing related to the request now in
00:03:39.680 this case we're using that employee ID
00:03:41.319 block variable to look up the employee
00:03:43.400 by ID and then setting the employee
00:03:45.439 variable all routes under this block can
00:03:48.159 then access the employee now you can get
00:03:50.840 similar behavior in other Frameworks
00:03:52.599 using before hooks but this provides a
00:03:54.840 simpler approach that avoids indirection
00:03:57.760 if you've ever had a debug issues in
00:03:59.200 your application
00:04:00.280 involving the use of hooks I think you
00:04:02.519 can appreciate this approach now what if
00:04:05.239 there is no matching employee for the ID
00:04:08.120 well in that case you can use the next
00:04:09.720 keyword to return nil From the Block
00:04:12.159 which Roto will treat as a 404 response
00:04:15.640 now this ensures there is a valid
00:04:17.199 employee for the rest of the block so
00:04:20.479 the next writing method is r. is with a
00:04:23.919 string name matcher now r. is is similar
00:04:27.639 to r.on except that it requires s that
00:04:30.120 the request path has been fully consumed
00:04:33.520 after all the mattress have been applied
00:04:35.880 so for our request since the employe and
00:04:38.120 segment seven segments have already been
00:04:40.360 consumed the remaining path is slash
00:04:42.840 name and the string name matcher will
00:04:45.400 match that segment and since the entire
00:04:48.280 request path has now been consumed by
00:04:50.680 the matchers given to the routing
00:04:52.000 methods the r. is Method will match and
00:04:54.560 it will yield to the block now inside
00:04:57.120 the r do is block the first method call
00:04:59.280 is r .g get which will match because the
00:05:02.280 request being handled uses the get
00:05:04.800 request method now the R.G block returns
00:05:08.320 a string hello followed by the employees
00:05:10.960 name and as the block returns a string
00:05:13.840 this string will be used as the response
00:05:16.240 body so let's see how a post request to
00:05:19.280 the same path will be handled so the
00:05:22.120 path of the request will still be fully
00:05:24.280 consumed by the matchers given to the
00:05:27.199 r.on and r.is methods
00:05:30.639 however the R.G method call will not
00:05:32.720 match as this is a post request and not
00:05:35.400 a get request so R.G will return nil
00:05:38.479 without yielding to the block the next
00:05:41.319 method in the block is r. poost which
00:05:43.840 will match because this request is a
00:05:45.880 post request so r. poost will yield to
00:05:48.479 the block now in this case we will use
00:05:50.560 the name parameter to update the
00:05:52.440 employees name and then we will redirect
00:05:54.880 the request and since no arguments are
00:05:57.440 given this will redirect to the same
00:05:59.800 path but using a get request and not a
00:06:02.479 post request so hopefully this example
00:06:05.560 was give able to give you a basic idea
00:06:08.240 for how roa's routing tree works the
00:06:10.599 most important part to remember is that
00:06:12.520 Roa gives you the power to do processing
00:06:14.720 related to the request at any point
00:06:17.440 during the routing process this reduces
00:06:20.000 duplication and indirection and results
00:06:22.759 in applications that are simpler and
00:06:24.840 easier to understand Simplicity is one
00:06:27.919 of R's four goals after 10 years
00:06:30.440 developing Roa I still think that the
00:06:32.400 primary benefit of Roa is it allows the
00:06:34.960 same application to be built more simply
00:06:37.919 than in other Frameworks another of
00:06:40.400 roa's goals is performance and unlike
00:06:42.759 the Simplicity goal where the benefits
00:06:44.560 are subjective you can see objective
00:06:46.720 differences between the performance of
00:06:48.400 Roa and other web Frameworks we're going
00:06:50.639 to look at two benchmarks the first is
00:06:53.400 r10k which is a synthetic Benchmark that
00:06:56.360 measures per request overhead and
00:06:58.759 scalability for large numbers of routes
00:07:01.360 now r10k benchmarks applications with 10
00:07:04.759 100 1,000 and 10,000 routes and to avoid
00:07:08.599 web server overhead it benchmarks using
00:07:10.759 the rack API directly so here are the
00:07:13.800 request per second results for Roa rails
00:07:16.800 Sinatra anami and camping and it shows
00:07:19.759 ra Roa is much faster than other
00:07:21.599 Frameworks now unfortunately the scale
00:07:23.840 of the graph makes it difficult to see
00:07:26.400 how the other Frameworks compare so
00:07:28.440 here's the same graph but using a
00:07:29.840 logarithmic scale and this still shows
00:07:31.840 Roa is much faster but it also shows
00:07:34.440 that Roa rails and Hanami all scale well
00:07:37.560 for large numbers of routes it shows
00:07:39.840 that snra and camping do not scale well
00:07:41.800 for large numbers of routes and that's
00:07:43.800 because both use a linear search of
00:07:45.960 routes during request
00:07:47.919 handling now rnk also provides memory
00:07:50.720 benchmarks and these show that RTO uses
00:07:53.120 less memory than other Frameworks rails
00:07:55.440 uses about three to four times more
00:07:57.800 memory than Roa in this bench mark
00:08:00.479 and while the r10k benchmarks are useful
00:08:02.759 they don't tell you much about the real
00:08:04.240 world performance differences so for
00:08:06.440 that the tech empow web framework
00:08:08.199 benchmarks do a better job teeken power
00:08:10.599 has been benchmarking web Frameworks in
00:08:12.360 many languages for over 10 years and Roa
00:08:15.159 has led the Ruby web framework
00:08:16.360 benchmarks ever since it was added in
00:08:19.560 2017 so here are the composite score
00:08:22.000 results for the most recent round of
00:08:24.159 tech and power benchmarks for Ruby web
00:08:26.159 Frameworks and Roa leads in every
00:08:28.560 category the way score for Roa it's
00:08:30.720 about twice what the rated score is for
00:08:32.599 rails and that lines up with results
00:08:35.120 I've seen from applications converted
00:08:37.279 from rails to Roa where the converted
00:08:39.839 Roa application is about twice as fast
00:08:42.760 as the benchmarks show Roa achieves its
00:08:44.760 performance goals it's the fastest Ruby
00:08:46.760 web framework scales well and it uses
00:08:49.320 the least memory it's the fastest
00:08:51.519 framework largely because it has the
00:08:53.480 lowest per request overhead road is
00:08:56.240 designed to minimize the amount of work
00:08:58.480 between when it receives IES the rack
00:09:00.160 request environment and when it starts
00:09:02.440 processing the routing tree R to scales
00:09:04.959 well because it uses a routing tree as
00:09:06.839 soon as a branch of the routing tree is
00:09:08.560 taken other branches at the same level
00:09:10.880 are no longer considered and finally Ro
00:09:13.519 to uses the least amount of memory
00:09:15.680 because it is designed around a small
00:09:17.440 core and that small core handles basic
00:09:20.399 routing and request handling all other
00:09:23.079 features are added via plugins rotus
00:09:26.040 core is itself a plugin and plugins can
00:09:28.519 override any part of Corea and any
00:09:31.079 previously loaded plugins as an example
00:09:33.959 of its minimalism rota's core does not
00:09:36.360 include template rendering template
00:09:37.920 rendering is supported via a plugin and
00:09:40.680 it's common to use this plugin if you're
00:09:42.399 writing applications that are targeting
00:09:44.519 browsers however if you're designing an
00:09:46.720 application that just serves API
00:09:49.079 responses via Json you wouldn't need it
00:09:51.959 in that case you'd probably want to use
00:09:53.560 the Json plugin which allows route
00:09:55.519 blocks to return arrays or hashes and
00:09:58.079 have those converted automatically Jason
00:10:00.000 and used as response bodies the reason I
00:10:03.040 refer to Roda as a toolkit is you can
00:10:05.519 think of each plugin as a tool and
00:10:07.560 different applications require different
00:10:09.279 tools and with Roa you only pay the
00:10:12.279 overhead cost for the tools that you
00:10:14.640 choose to use R ships with over 120
00:10:17.839 plugins to handle the needs of a wide
00:10:19.959 variety of web applications and there
00:10:22.079 are numerous external rooto plugins to
00:10:24.680 handle additional needs so this approach
00:10:27.240 of having a small core and shipping all
00:10:29.320 all optional features as plugins is how
00:10:31.640 Roa achieves its goal of
00:10:33.800 extensibility roa's final goal is
00:10:36.000 reliability and Rota achieves this goal
00:10:38.519 by combining two development approaches
00:10:40.839 the first is immutability so Rota
00:10:43.480 applications are designed to be frozen
00:10:45.680 in production and when testing and this
00:10:47.839 reduces the possibility for thread
00:10:49.480 safety issues as well as memory leaks
00:10:51.839 due to unexpected object retention now
00:10:54.440 immutability is not just for reliability
00:10:57.079 in Roa either in Roa immutability also
00:11:00.720 improves performance when you freeze
00:11:03.160 your Roa application Roa knows there'll
00:11:05.480 be no further configuration changes to
00:11:07.720 it Roa then determines whether the
00:11:10.000 methods that it offers that are designed
00:11:11.720 for extensibility have not been
00:11:13.720 overridden and in that case it overrides
00:11:16.320 the default extensible methods with
00:11:18.760 optimized methods and that gives you the
00:11:20.920 best of both worlds extensibility when
00:11:23.320 you need it and maximum performance when
00:11:25.920 you don't the second development
00:11:28.200 approach related to reliability I refer
00:11:29.920 to as Pollution Control more explicitly
00:11:32.839 namespace pollution control or it limits
00:11:35.800 the constant the pollution of your
00:11:38.079 constant method and instance variable
00:11:40.240 name spaces in your
00:11:42.000 application all of the internal
00:11:43.880 constants in Roa are prefixed with Roa
00:11:46.680 So to avoid conflicting with userdefined
00:11:49.200 constants Roa limits instance variable
00:11:51.720 pollution by prefixing all internal
00:11:54.320 instance variables in route block scope
00:11:56.560 with an underscore if you've ever
00:11:58.639 developed a notra application and Tred
00:12:00.519 to use request or response instance
00:12:02.480 variables you will appreciate this Ro
00:12:05.519 limits method pollution by only defining
00:12:07.839 six methods in rot to block scope beyond
00:12:10.560 the methods that are defined in object
00:12:12.240 and some private methods that begin with
00:12:13.600 an underscore and this makes it less
00:12:15.440 likely that a user user defined method
00:12:17.760 will conflict with a Roa method so now
00:12:20.839 that I've given you a brief Taste of Roa
00:12:22.639 and discussed how Roa has achieved its
00:12:24.480 goals I can start discussing the first
00:12:26.720 10 years of Roa now roa's first Rel
00:12:29.160 release was on July 30th 2014 and its
00:12:32.240 most recent release the 125th release
00:12:35.360 was 3 days ago now I don't like waiting
00:12:38.000 long to use new features so Roto Falls a
00:12:40.880 simple to understand release schedule
00:12:43.079 there's a new rotto release every month
00:12:45.279 around the middle of the month ever
00:12:46.920 since
00:12:48.560 2014 I also don't like it when changes
00:12:50.760 to a library break my applications so
00:12:53.279 roota places a high priority on
00:12:55.160 backwards compatibility I think the
00:12:57.600 compatibility is so good that the
00:12:59.440 majority of applications that worked
00:13:01.079 with the first release Roa 0.9 would
00:13:04.000 still work if you upgraded them to the
00:13:05.600 latest release R to 3.86 with one main
00:13:09.160 exception if we go back to our first
00:13:11.199 example we see that it uses the integer
00:13:13.440 class matcher however Roa did not
00:13:15.560 support using the integer class as a
00:13:17.279 matcher until Roto
00:13:18.839 2.27 before Roto 2.27 this type of
00:13:22.000 matcher would generally be written using
00:13:23.760 what is referred to as a placeholder
00:13:25.240 string with placeholders in the string
00:13:27.320 being prefixed by colon now this style
00:13:30.160 resulted in two issues first it resulted
00:13:33.000 in redundancy most developers would name
00:13:35.440 the placeholders similar to The Block
00:13:37.440 variables that's not technically a
00:13:39.360 problem but it is a tad annoying the
00:13:41.959 actual problem was a performance problem
00:13:44.120 which is that you needed to scan all
00:13:45.800 strings that are used as matchers to see
00:13:47.959 if the strings contain placeholders and
00:13:50.160 then treat the string differently if it
00:13:51.800 had a placeholder strings are the most
00:13:54.079 common type of matcher so this check
00:13:56.079 resulted in a measurable slowdown even
00:13:58.639 if you not using placeholders so Rota 3
00:14:01.720 removed support for placeholders in
00:14:04.000 string matchers by default and in order
00:14:06.000 to support backwards compatibility Rota
00:14:08.360 3 shipped with a placeholder string
00:14:09.920 mattress plugin now I analyzed a couple
00:14:12.360 of my open source applications checking
00:14:14.480 out the commit where the application was
00:14:16.600 converted from Sinatra or rails to Roa
00:14:19.639 0.9 and trying it with the current
00:14:21.959 version of Roa and in both cases adding
00:14:24.839 the placeholder string matchers plugin
00:14:26.839 was the only rotor related change NE
00:14:29.120 necessary to get the specs passing with
00:14:31.360 the current version of Roa I mentioned
00:14:34.440 that one of the reasons for breaking
00:14:35.800 backwards compatibility was to improve
00:14:38.440 performance so how much did this change
00:14:40.600 and other changes improve roa's
00:14:42.639 performance over the last 10 years to
00:14:45.880 determine that we're going to look at
00:14:46.880 some more r10k benchmarks to see how
00:14:49.120 roa's performance has improved over time
00:14:52.279 additionally as Roa is a fork of another
00:14:54.079 web framework named Cuba we're also
00:14:56.079 going to compare Roa to Cuba so let's
00:14:58.279 start with Roda as initial release
00:14:59.839 compared against the current Cuba
00:15:01.320 release at the time as you can see
00:15:03.279 performance is basically the same for
00:15:05.480 the initial release I was focused on
00:15:07.399 differences in route block handling
00:15:09.199 handling block responses and getting the
00:15:11.399 plugin system working I wasn't focused
00:15:13.519 on performance since CUO was already
00:15:16.000 much faster than other Ruby web
00:15:17.519 Frameworks at the time less than a month
00:15:20.120 after the initial release I released Roa
00:15:22.440 1.0 and this had a massive boost in
00:15:25.079 performance over the initial release
00:15:26.639 with a number of additional
00:15:27.959 optimizations at the time most of the
00:15:30.480 matchers in Roa were based on regular
00:15:33.000 expression scanning and the most
00:15:34.759 important optimization was the caching
00:15:36.600 of regular Expressions instead of
00:15:38.600 generating a new regular expression for
00:15:40.800 every matcher about 6 months after
00:15:43.360 releasing Roa 1.0 I released Ro to 2.0
00:15:46.480 which improved performance over 1.0 by
00:15:48.880 about 20% now this performance
00:15:51.240 Improvement was due to reducing
00:15:52.759 allocations during matching so that each
00:15:55.279 match attempt did not modify the request
00:15:58.000 environment
00:15:59.759 about 2 and a half years after that I
00:16:01.440 released order a 3.0 which improved
00:16:03.360 performance over 2.0 by about
00:16:06.279 40% so this performance Improvement was
00:16:09.199 mostly due to avoiding regular
00:16:11.079 Expressions during matching and the
00:16:12.839 remover of placeholders during string
00:16:14.519 matching instead of regular Expressions
00:16:17.279 string Methods such as start with an
00:16:19.360 index are used and this idea was taken
00:16:21.680 from syyro a routing Library by the same
00:16:24.079 author as Cuba by January 2021 with the
00:16:27.720 release of Rota 3.4 40 performance had
00:16:29.920 increased another
00:16:31.160 15% this performance increase was due to
00:16:33.680 a couple of optimizations during this
00:16:35.720 time period is when I added the
00:16:37.240 optimization during application freezing
00:16:40.120 additionally the performance of string
00:16:41.560 and segment matchers was improved about
00:16:43.560 15% and terminal matching by about
00:16:46.880 400% between R to 3.40 and 3.60
00:16:50.560 performance increased another 30% and
00:16:53.199 this was due to additional optimizations
00:16:54.839 on the most common matchers R's current
00:16:57.079 performance is about the same as Roa 3
00:16:59.120 60 so between roa's initial release and
00:17:01.959 the current release performance in this
00:17:03.839 Benchmark improved by a factor of 12 I
00:17:07.760 think that's pretty amazing considering
00:17:09.160 that even at roa's initial release it
00:17:11.199 was one of the fastest Frameworks
00:17:13.600 however this is not the limits of roa's
00:17:15.280 performance using the optimized string
00:17:17.439 matchers optimized segment matchers and
00:17:19.480 plane hash response
00:17:21.000 headers uh plugins performance can be
00:17:23.799 increased another
00:17:25.439 35% and this does require some small
00:17:28.199 sacrifices usability though now r10k is
00:17:32.320 a routing and per request overhead
00:17:34.520 Benchmark and Roa has improved greatly
00:17:36.320 over the years at that however that's
00:17:38.720 not the only way that Roa has improved
00:17:40.559 performance many of the plugins that
00:17:42.600 ship with Roa have been optimized as
00:17:45.000 well for example the render plugin has
00:17:47.240 shipped with every release of Roa but it
00:17:49.440 and related plugins were extensively
00:17:51.240 optimized a few years ago for simple
00:17:53.520 templates the render plugin is about
00:17:55.039 four times faster than it was originally
00:17:58.440 speaking of plugins rot to 0.9 shipped
00:18:01.159 with 15 plugins and R to 3.86 ships with
00:18:04.240 over 120 plugins more than eight times
00:18:06.840 as many as the initial release so I'm
00:18:09.720 going to take you on a quick tour of the
00:18:11.679 last 10 years of Roto plugins in the
00:18:14.720 initial release in addition to rendering
00:18:16.679 Ro ship with plugins for handling
00:18:18.880 exceptions customizing default headers
00:18:21.320 and 404 responses handling flas messages
00:18:25.360 streaming responses and operating as
00:18:27.559 rack middleware however one of the most
00:18:29.919 important plugins was the ability to use
00:18:32.679 separate route blocks if you remember
00:18:34.960 back to our original example I mentioned
00:18:37.280 that all requests are yielded to the
00:18:39.240 route block and the route block
00:18:40.600 determines the response now in Ruby you
00:18:43.400 cannot split a block across multiple
00:18:45.919 files and having all routes in a single
00:18:48.240 file only makes sense for small
00:18:50.679 applications to handle large
00:18:52.400 applications you need a way to separate
00:18:54.360 the route block and even the very first
00:18:56.760 release of Rus supported that via the
00:18:58.880 multiroute plugin so with the multiroute
00:19:01.120 plugin you could call r. multiroute in
00:19:03.640 your main routing block and it would
00:19:05.480 dispatch to separate routing blocks
00:19:07.320 based on the next segment in the
00:19:09.400 remaining path this these those routing
00:19:12.120 blocks would generally be stored in
00:19:13.919 separate files based on the route
00:19:15.520 segment name like this and that made it
00:19:17.760 simple to organize large applications in
00:19:19.960 Roa and allowed even the first release
00:19:21.880 of Roa to scale from simple single file
00:19:24.760 applications to decent sized
00:19:27.720 applications order 1.0 added 11 new
00:19:30.520 plugins not in the initial release and
00:19:33.000 these included plugins for returning
00:19:35.039 arrays and hashes as Json cross-site
00:19:38.039 request forgery protection rendering a
00:19:40.400 collection of partials in one call and
00:19:42.799 having a separate view subdirectory for
00:19:45.159 separate branches in the routing tree
00:19:47.799 Additionally the render plugin was
00:19:49.360 expanded to support the automatic
00:19:51.200 escaping of output and templates greatly
00:19:53.840 reducing the likelihood for cross-site
00:19:55.640 scripting issues I think my favorite
00:19:57.919 plug-in Edition in 1.0 is symbol views
00:20:00.720 so the symbol views plug-in is very
00:20:02.480 simple but it allows you to replace
00:20:04.720 manual calls to view to render templates
00:20:08.039 and just have the route block return a
00:20:09.520 symbol and this small change dries up a
00:20:12.080 lot of Route code and makes the common
00:20:14.000 case of rendering a template inside a
00:20:16.240 layout even simpler than it is in
00:20:18.559 Sinatra or rails now not everyone is a
00:20:21.480 fan of this tur style however just
00:20:24.000 because I think a particular style is
00:20:25.720 nicer does not mean I think I should
00:20:27.640 force it on all R users between R 1.1
00:20:31.440 and 1.3 25 more plugins were added
00:20:34.600 including plugins for managing HTTP
00:20:37.080 caching incrementally rendering
00:20:39.039 templates and compiling compressing and
00:20:41.240 serving asset files R 1.2 added the
00:20:44.320 mailer plugin which brought the benefit
00:20:46.240 of routing trees to sending emails from
00:20:49.120 applications so here's an example that
00:20:51.080 uses the mailer plugin generally you use
00:20:53.600 the mailer plugin in a Rota sub class
00:20:55.840 designed specifically for sending emails
00:20:58.799 unlike a ro to web application which is
00:21:00.679 designed to handle HTTP requests a rot
00:21:03.520 to mail application is designed to
00:21:05.080 handle internal requests however sending
00:21:07.799 mail with a mailer plug-in is done by
00:21:09.559 providing a path just like with an HTTP
00:21:12.440 request a Rota mail application uses the
00:21:15.080 same basic routing methods that a r to
00:21:17.200 web application uses and just like in a
00:21:19.600 r to web application at any point when
00:21:22.080 handling a mail requests the root to
00:21:24.360 mail application can do processing
00:21:26.159 related to the mail so here we are
00:21:28.159 setting the sender and recipient
00:21:29.919 addresses so those don't need to be
00:21:32.000 duplicated inside every maale handling
00:21:34.720 block now the r. mail method is used to
00:21:37.240 handle mail routes and it operates
00:21:39.320 similarly to R.G get and r. poost in
00:21:42.840 this case the time off matcher matches
00:21:44.919 the remaining path so the method will
00:21:47.080 yield to the block and the block sets
00:21:49.320 the subject for the mail and Returns the
00:21:51.520 symbol for the male template to render
00:21:53.600 and returning a symbol works here
00:21:55.000 because this mail application also uses
00:21:57.200 the symbol of views plugin
00:21:59.960 now between Rota 2.0 and 2.29 22 more
00:22:03.480 plugins were added these included
00:22:05.360 support for sending preload headers for
00:22:07.720 assets serving public files at specific
00:22:10.440 places in the routing tree rewriting
00:22:12.880 paths prior to routing Parson Jing
00:22:15.520 request bodies to parameters fast 01
00:22:18.520 routing to static paths and having the
00:22:21.000 routing tree support file extensions in
00:22:23.400 the request path especially order 2.27
00:22:26.760 added the class matchers plug-in which
00:22:28.840 allows you to specify the handling of
00:22:30.840 arbitrary classes that are used as
00:22:33.240 matchers going back to our initial
00:22:35.240 example we see that we are using the
00:22:37.080 integer matcher which yields an integer
00:22:39.440 we're then looking up the employee using
00:22:41.360 the integer and have to manually handle
00:22:43.600 the case where that lookup fails using
00:22:46.120 the class matchers plugin we can
00:22:47.480 simplify this we can register the
00:22:49.840 employee class as a matcher and build on
00:22:52.559 top of the integer matcher if there's a
00:22:54.760 match by the integer matcher if the
00:22:56.480 value is yielded to the block as an
00:22:58.080 integer
00:22:59.039 and the block can then do the employee
00:23:00.799 lookup and that allows the routing tree
00:23:02.919 to be simpler every case where you're
00:23:04.919 trying to match an employee you can pass
00:23:07.279 the employee class as a matcher and it
00:23:09.679 will yield the employee object to the
00:23:12.039 routing block if the segment was for a
00:23:14.520 valid employee and if the segment was
00:23:16.880 not for a valid employee it just
00:23:18.840 wouldn't
00:23:19.840 match between Rota 3.0 and 3.29 12 more
00:23:24.320 plugins were added including support for
00:23:26.840 encrypted sessions early hints content
00:23:29.799 security policies processing incoming
00:23:32.440 emails using a routing tree logging in
00:23:35.039 common log format showing nice exception
00:23:37.600 handling pages in development splitting
00:23:40.080 the rotting tree into subt trees without
00:23:42.159 using regular expressions and supporting
00:23:44.679 stronger cross-site request forgery
00:23:46.480 protection with tokens specific to the
00:23:48.960 request method and path order 3.3 added
00:23:52.400 a typ cast prams plugin for handling the
00:23:54.880 typ casting of submitted parameters to
00:23:56.840 expected types so here's an example of
00:23:59.360 use showing automatic conversion of a
00:24:01.360 given parameter to a positive integer
00:24:03.640 ensuring that ATT attackers cannot try
00:24:05.080 to submit an array or hash Now typ cast
00:24:08.039 prams has support for nested parameters
00:24:10.520 typecasting arrays of values to expected
00:24:12.799 types and custom parameter types it's
00:24:15.039 designed to be simple and not ver
00:24:17.360 Bose between Rota 3.30 and 3.59 17 more
00:24:21.679 plugins were added and these included
00:24:23.679 support for host authorization trying
00:24:26.440 multiple render engines and multiple
00:24:28.159 view directories when rendering
00:24:29.799 templates using arbitrary objects as
00:24:32.279 matchers during routing supporting
00:24:34.480 multiple directories for public file
00:24:36.080 serving at different places in the
00:24:37.760 routing tree and a simpler approach to
00:24:40.000 dispatching to separate routing trees
00:24:42.000 which can automatically set the view
00:24:43.520 subdirectory during the dispatch now
00:24:46.200 between R 3.60 and the current version
00:24:48.640 3.86 19 more plugins were added and
00:24:51.679 these plugins included support for
00:24:53.720 handling arbitrary objects returned from
00:24:55.919 routing blocks autoloading hash branch
00:24:58.880 for faster development and testing
00:25:01.039 setting a permissions policy enforcing
00:25:03.399 cookie Flags handling invalid request
00:25:06.039 bodies and measuring line and Branch
00:25:08.399 coverage of templates even in rby
00:25:10.600 versions that do not support coverage
00:25:12.480 for eval code order 3.79 added an hmac
00:25:16.880 paths plugin which allows you to easily
00:25:19.279 prevent path enumeration by including an
00:25:21.640 hmac in the path so going back to our
00:25:24.039 initial example we see that this allows
00:25:26.320 anyone to issue requests for this Branch
00:25:29.360 what if you want to prevent someone with
00:25:31.159 access to the application from
00:25:32.720 enumerating the employees well using the
00:25:35.440 hmac paths plugin we can wrap the
00:25:37.559 routing Block in r. hmac path and when
00:25:40.880 generating paths in your application you
00:25:43.080 would call hmac path with the path which
00:25:45.799 would prefix an hmac and some metadata
00:25:48.520 such that r. hmac would consider it
00:25:50.559 valid and the hmac paths plugin was
00:25:53.640 expanded in R to 3.80 to support session
00:25:56.200 specific hmax so that paths valid for
00:25:58.679 one logged in user would not be valid
00:26:00.799 for a different logged in user it was
00:26:02.760 expanded again in Moda 3.81 to support
00:26:05.320 paths that are only valid for a limited
00:26:07.799 time so that's a brief tour of plugins
00:26:10.760 that Roa has added in the first 10
00:26:13.520 years going to finish up this
00:26:15.279 presentation by discussing two open
00:26:17.600 source applications that are built on
00:26:19.320 top of Roa and how they are using roa's
00:26:21.760 features the first application is KFA
00:26:24.520 web which is a web front end for KFA a
00:26:27.520 ruby gem for with cfco which is a
00:26:29.360 distributed publish subscribe Cube now
00:26:31.919 crafco web ships all of its asset files
00:26:34.279 inside the gem and it uses Rus public
00:26:36.600 plugin and it serves the assets using a
00:26:39.480 path based on the gem version and this
00:26:42.039 automatically handles cash and
00:26:43.520 validation by using A New Path for each
00:26:46.279 gem version craft web uses the custom
00:26:49.279 block results plugin so that route
00:26:51.039 blocks can return craft web specific
00:26:53.159 objects which are translated into HTTP
00:26:55.559 responses and this reduces duplication
00:26:58.720 inside the routing blocks now the second
00:27:01.320 application is UB Cloud UB cloud is an
00:27:03.320 open source alternative to Amazon web
00:27:05.279 services it's being developed by a
00:27:07.080 startup also called UB Cloud now UB
00:27:09.640 Cloud uses the rodo authentication
00:27:11.240 framework to handle authentication rodo
00:27:13.600 is Ruby's most advanced authentication
00:27:15.960 framework with built-in support for
00:27:18.200 multiactor authentication such as top
00:27:20.840 and webo in now rodo is a Roa plugin but
00:27:24.480 you can use rodo even in non-r
00:27:26.320 applications by using R's middle plugin
00:27:29.000 and using the Roo application as
00:27:30.960 middleware now UB Cloud uses multiple
00:27:33.399 rodo configurations because it uses rodo
00:27:35.760 to handle authentication both for
00:27:37.440 browser logins as well as for its Json
00:27:41.080 API this is the section of UB Cloud's
00:27:43.440 main route block which is designed to
00:27:45.240 handle browser requests and GitHub web
00:27:47.799 hooks now UB cloud is a decent sized
00:27:50.240 application so it uses the hash branches
00:27:52.519 plugin to separate the routing trees it
00:27:55.120 actually has two separate dispatches to
00:27:56.919 routing trees here this one is for the
00:27:58.960 main application and it's used for
00:28:01.120 logged in users web hooks dispatch to a
00:28:04.000 different set of routing trees as they
00:28:05.880 don't need cross-site request forgery
00:28:07.679 checks nor do they require the same
00:28:09.760 authentication as logged in users and
00:28:12.080 this type of setup is possible in other
00:28:13.679 Frameworks but it is significantly
00:28:15.480 simpler in Roa so that's how some
00:28:17.880 production open source applications are
00:28:19.919 using Roa to simplify their web
00:28:22.000 development as we get near the end of
00:28:23.760 this presentation I'm happy to announce
00:28:25.720 that after 10 years Rota recently passed
00:28:28.279 10 million downloads so if you haven't
00:28:30.440 already tried using Roa now is a great
00:28:32.799 time to start if you're wondering about
00:28:35.080 the future of Roa I'm happy to announce
00:28:37.120 that I've joined UB cloud and part of my
00:28:39.080 job is continuing to maintain Roa and
00:28:41.559 other open source libraries on top of
00:28:43.440 which UB cloud is built I hope you had
00:28:46.080 fun learning about the first 10 years of
00:28:47.960 Roa if you're looking to reducing your
00:28:49.919 Cloud spend or you want an easy way to
00:28:51.840 deploy Ruby apps to the cloud with Kamal
00:28:54.000 stop by the UB Cloud booth and talk to
00:28:55.640 us we would love to work with you on it
00:28:58.640 and that concludes my presentation I'd
00:29:00.200 like to thank all of you for listening
00:29:01.440 to me I have maybe a minute for
00:29:03.679 questions yeah is there an instance
00:29:05.679 where you wouldn't want to use Roa well
00:29:07.440 it depends on what sort of what you're
00:29:09.240 doing obviously like compared to rails
00:29:11.519 uh if you're dealing with a lot of
00:29:12.600 people that already know rails or you're
00:29:14.080 using libraries that work with rails
00:29:16.000 you'd have to find equivalent stoa now I
00:29:17.919 think for a lot of the major stuff
00:29:19.399 that's probably uh possible um but you
00:29:22.799 might have three or four options in
00:29:24.240 rails and only one in Roa for more Niche
00:29:26.559 cases you might have options in and not
00:29:28.679 have options in Roda so a lot of it
00:29:30.440 depends on what you're doing and how
00:29:31.600 much code you want to reuse out there um
00:29:33.919 and whether or not there's Alternatives
00:29:35.360 that you can use in Roa so also depends
00:29:38.760 on how familiar the team is with rails
00:29:41.240 versus uh with Roa
Explore all talks recorded at RubyConf 2024
+64