This video contains 12 individual talks

SF Bay Area Ruby Meetup - November 2024
+12
See all speakers
See all 12 speakers

Sections in this recording

SF Bay Area Ruby Meetup - November 2024
Irina Nazarova, Konstantin Gredeskoul, Chris Fung, Jeremy Evans, Todd Kummer, Ken Decanio, Cameron Dutro, Dave Doolin, Brian Durand, Espartaco Palma, Benjamin Atkin, and Brad Gessler • November 19, 2024 • San Francisco, CA • Talk

​​Hey, Bay Area builders and tinkerers!

While Ruby may not dominate the headlines, it's the silent force behind the Bay Area's most successful startups. From GitHub and Stripe to Chime and Stackblitz, Ruby powers teams that go HUGE with less.

​Join us as we re-kindle the SF Ruby community's flame! It is a unique place to meet authors of your favorite open-source tools (or members of the Ruby core team), incredibly experienced engineers and new converts, as well as new startup founders building and experimenting with the power of Ruby and Rails. It's a chance to meet every month and make new Ruby friends.

Our meetups explore Rails at scale, practical Hotwire implementations, methods for building AI-native apps and so much more—all through Ruby's uniquely productive lens.

For our November gathering, Academia.edu is our gracious host! This time, the speaker lineup is unmatched: Jeremy Evans, author of "Polished Ruby," Sequel, and Roda, is joined by Konstantin Gredeskoul (Academia), Chris Fung (Binti), and Brad Gessler (Rocketship, Fly).

Address: 580 California St. Suite 400 San Francisco, CA 94104

https://lu.ma/f4pfsigc

SF Bay Area Ruby Meetup - November 2024

00:00:00.439 everybody it's amazing to see you all today amazing to see you all chatting connecting to one another new faces um
00:00:10.160 familiar faces uh friends so let's uh we're GNA
00:00:15.799 have fun today we are up for treat and thanks to Academia for hosting us today
00:00:21.560 let's give them a round of applause hi I'm Arena I I run company
00:00:29.439 called evil martians uh but I want to start with
00:00:35.520 something it's how I see what we're doing
00:00:41.239 here and nice I wasn't sure how it's going to
00:00:47.239 play um so I think uh what we we are doing with we are connecting four
00:00:53.559 distinct areas where things are happening so first of all they are Engineers right learning Rob
00:01:00.440 then there are new companies or startups built at Ruby then there are big and successful
00:01:07.880 Enterprises bu Ruby and then the maybe the biggest part right is the language
00:01:14.040 and the Frameworks we'll hear about some of them
00:01:19.159 today and the open source and the ecosystem and here today there are many
00:01:26.640 people from all those different spheres right there are people that that use
00:01:33.119 Ruby that learn Ruby that love Ruby there are people working in different types of companies and there are people
00:01:39.360 building out the ecosystem and again this this could be all you know the same
00:01:45.880 person um but um what I think is happening is that if you think about
00:01:52.960 community community is a way to to help those different types of people those
00:02:00.280 different areas get together and build connections and help each other for
00:02:06.719 example uh authors of Open Source need feedback and need to know that you're
00:02:14.040 using it uh at your workplace or for your site project or you know uh
00:02:20.640 Engineers looking for a job of course need to find that uh companies need to be able to hire um startups need to be
00:02:27.920 able to find the right tools to solve their problems Etc so I want this community to be this place and I think
00:02:35.640 this is happening because we have all of you extremely talented people in the
00:02:41.239 room together so thanks so much for making this all
00:02:46.599 happen thank you and um we already have uh three EV mon um so
00:02:59.120 there's today's event there's also the next event is going to be December the 3D so please use the link um lumsa Ruby
00:03:09.200 uh sign up there and you will have updates for all the future events and please uh please come please
00:03:17.159 join please bring your questions use the open mic session to bring your questions
00:03:22.680 your announcements your learnings you know bring your wings and uh everything
00:03:28.599 um got here Al December is a special month um I'm not sure if we going to be
00:03:36.280 doing this but I hope maybe oh my God it's gonna
00:03:43.519 be um so what do I propose us to do next time it's December the 3D before
00:03:49.720 hopefully before everybody's off someplace for the holidays but maybe
00:03:55.200 let's bring cookies
00:04:00.280 do something like that and bring your holiday mood and bring your um Vibes
00:04:08.000 costumes um so yeah and finally we have our the we have something planned for
00:04:14.159 January already uh again on product board and yeah December we we meet at Sentry we
00:04:20.959 have something in product board we talk to three more companies that want to host event so it's it's it's pretty
00:04:27.320 active so the only thing we need is you and um yeah with that I'm I'm super
00:04:32.960 excited to um to now proceed to the kind
00:04:38.240 of to the back part of this to the the talks and we have Constantine then Chris
00:04:44.400 but then we have a break open mic bread and joury so yeah uh with that
00:04:51.759 Constantine please take it away
00:05:03.360 SL technical difficulties okay this is a meet up we're always going to be reconnecting
00:05:11.120 connecting spending time good luck it's not all right
00:05:17.240 everything work thank you for that
00:05:22.840 introduction thank you for organizing these events um we used to have really
00:05:28.520 good uh SF Community back in a day when I was St know kind of on so thank you
00:05:34.280 for starting it for all of us um my talk today is um uh on design
00:05:41.440 for loose coupling in Ruby and um I think it's a topic that
00:05:46.759 hopefully will be uh relatable to a lot of people here uh because um it's kind
00:05:53.960 of the only one of the only ways we have uh in our disposal to kind of break up
00:06:00.960 really big code bases and make them more manageable
00:06:06.199 um so rails only gives you a starting point for your application um it does not tell you how to organize your actual
00:06:13.319 business logic and so result is people just kind of fill up these model directories flat and
00:06:21.080 uh at some point maybe start creting directories um and so on and so it
00:06:27.000 eventually get pretty complicated so um I write sometimes spaghetti Cod who
00:06:33.599 else here write spaghetti Cod
00:06:39.240 intentionally excellent um so nobody wants in spaghetti cold intentionally but we just happen to um Do It um now
00:06:49.319 I'm sorry I had to put this wordy slide with the definition U but uh in my own
00:06:55.240 words essentially you know loose coupling is when you have uh very few
00:07:00.759 connections between high level abstractions modules and lots of connections within it um You can call it
00:07:07.919 tight coupling tight cohesion High cohesion uh loose coupling low cohesion
00:07:13.599 and so on lots of uh synonyms but uh the point is the same if you have
00:07:19.520 connections messages passing all over the place um you have a spaghetti uh if
00:07:24.960 you if you don't have it uh somehow constrained
00:07:30.280 so with this definition out of the way um when you begin your application Wells
00:07:36.039 or not you just going to tightly couple your code no matter what because why not
00:07:42.319 um surface area is small um structions are unnecessary so um in the in the
00:07:48.120 beginning I think it's totally entirely fine um this is kind of a maybe not
00:07:54.520 exactly perfect visualization of how your spaghetti code would look like but you can imagine
00:08:00.720 um and um after a while however things get harder with exponential complexity
00:08:06.039 because it starts to look like this and so what is the alternative
00:08:11.360 alternative is you can design app as a set of inter operating modules so subsystems with clear boundaries and
00:08:17.080 enforcement capabilities you don't do this from the beginning of course but it might look
00:08:22.440 like this uh where you have a module with lots and lots of meaningful connections inside maybe direct access
00:08:29.520 maybe you have database access but then between these modules these uh thick arrows represent kind of API calls
00:08:36.200 through uh a public interface that has been announced by this module um so you start thinking about it
00:08:44.200 when your app no longer fits in any individual head or maybe you can think ahead knowing that this is going to come
00:08:51.320 to you and that case if you're building an application that you know is going to be complex you might start by thinking
00:08:58.519 how can I parti my models into models that interoperate
00:09:03.680 within but don't talk much to the outside system so um another reasons to stop
00:09:12.360 thinking about it is when there's just too many cooks in the kitchen um or when develop a productivity just Crees to
00:09:20.320 hold so why do we care about this what do we get from it and what do we
00:09:26.279 lose and to step I want to step a little back um as I usually do um I kind of
00:09:34.000 imagine most people here write commercial software you guys write um probably web or some applications that c
00:09:40.880 in production and producing Revenue question what makes your software
00:09:47.160 good or I'm actually putting kind of an answer there how do you know your
00:09:52.200 software meets the needs of the business that's a really important question to ask yourself
00:09:59.760 because um if your software for example is incredibly expensive to maintain and
00:10:06.160 run um any margins are low that will kill your business um so reducing the
00:10:13.880 cost of running software is a really good thing because it allows a business to survive so the answer uh to that
00:10:23.120 question um the question was uh sorry
00:10:29.560 go through this again um that's the question why do we care
00:10:36.639 about this uh what do we get so uh you get different answer from different
00:10:41.839 people Co product maybe had a product will say well how well does a software adapt to our changing requirements
00:10:48.639 that's how we know it meets business needs how quickly we can prototype does launch new ideas on product features is
00:10:54.920 a reliable scalable and secure this is probably the extent of how uh CEO or um
00:11:01.560 had a prodct things about field of software in the uh business now cf4 and
00:11:08.639 investors may have another angle how much do it cost and does the cost now to
00:11:13.720 maintain and Advance this application is it massively expensive is it too expensive what is too expensive how do
00:11:21.399 we know well one way of measuring this is finding the cost of running service for a single
00:11:26.959 user I don't know I'm curious has any anyone ever done this exercise
00:11:32.480 for wow that's awesome um I'm really curious to hear what you guys found but
00:11:39.279 um I'm guessing it's uh a lot so um yeah those are the different
00:11:45.680 ways we look at whether software fits business requirements um and ultimately what we
00:11:52.000 work is that the work apps the work the app works correctly that um it's within
00:11:57.360 the SLA it's support SPS rapid prototyping feature development has
00:12:02.920 tests and metrics above should not decline replication or team size as it
00:12:07.959 grows now what I wrote here are nice to have for every project I've been on has
00:12:15.320 it always been like that not even close you can have two or three of these
00:12:21.480 uh but maybe not all five and so I think that this talk about Lo coupling uh is
00:12:28.800 Lar about how to get that very last point because we already know how to do
00:12:35.760 the first four but the last one is the hard
00:12:42.680 one um okay I'm going to skip through this um so the question becomes how do
00:12:49.399 we go from a small messy app with the super Hy productivity that raes gives us to very large app without losing too
00:12:56.440 much that productivity that we were enjoying one possible answer could be software
00:13:02.079 design that's forward looking as it anticipates the future but does not prescribe it and what's the best way to
00:13:08.839 do it um software that anticipates changes then lose
00:13:15.120 cou it is one of the simplest things to understand conceptually but also one of
00:13:20.440 the hardest to do consistently well so what are the different ways we
00:13:25.720 can actually write Loosely couple code and I want to ask you guys uh give me like three or
00:13:31.920 four things anybody what can we do to get our code
00:13:39.000 Lo the cou anyone there a service pattern Serv pattern great anything
00:13:46.240 else yeah like C IDs instead of active record objects so data objects basically
00:13:52.680 gra yeah separate concern opposed to the whole thing yeah
00:13:58.519 well those are good those are all parts of the same uh thing but um I present you three um answers that I U put up U
00:14:06.880 the first one is by modularizing application and using facade pattern to interface with other modules and that's
00:14:13.199 packwork approach we're going to talk more about packwork in a little bit second one is by using observable
00:14:19.360 pattern it's a pattern that allows you to decouple subscribers from event producer um and use events it's very
00:14:26.920 convenient uh Ruby comes with observable already built in um I actually wrote um
00:14:32.560 gem called ventable um that um expands on this concept and allows you to create
00:14:37.759 events that carry information there's another gem called whisper that does something similar um it's a pretty good
00:14:44.880 way to separate your concerns to subscribe to something and be notified later
00:14:51.199 on and then a third one is by using a verion of control dependency injection um that's how you sort of end
00:14:58.360 up not depending on a code spe on a code class definition you can get it passed in and avoid direct assenti so those are
00:15:05.920 kind of different levels of loosely coupled uh the last two obiously design
00:15:11.120 patterns first one is more of quod organization so where do we go from here
00:15:18.600 what we're going to do is next is we're going to sketch up um um uh L the
00:15:24.279 coupled modules for a typical eCommerce Marketplace believe it or not it's based on real application we'll look at
00:15:30.319 several patterns that participate on L coupling such as facade library and version of control a little bit more
00:15:35.920 detailed we'll look how packo can be applied incrementally and gradually to migrate a very large app into well
00:15:41.480 defined modules so um here is the e-commerce
00:15:46.959 Marketplace I want to point out the two barcodes on the side uh if you get them
00:15:52.199 um they will take you to academia's job page uh there's going to be more of them
00:15:57.360 at the end so what is a Marketplace Marketplace is sellers buyers and the marketplace itself think Amazon think
00:16:04.720 Etsy whatever so think in your head what sort of data model would you be needing
00:16:10.639 to implement if you had to build this and what are the natural modules
00:16:17.639 that you could stuff various models into but basically put become groups or
00:16:23.480 modules together well um
00:16:30.639 this is uh what I am uh basically proposing here um this is what we ended
00:16:38.120 up doing but this is not how we got there we got there from the schema
00:16:44.480 diagram which kind of showed us that certain tables have a lot of connections
00:16:49.560 other tables don't so um here what you see is six different modules the left
00:16:56.000 one is called Marketplace stores it has store information store details store owners feed product feeds from maybe
00:17:03.880 Shopify now in the middle you see product catalog that's where you browse it has products variance inventory and
00:17:10.679 it pulls these products from the um Marketplace store so belongs to that um
00:17:16.360 we're going to skipe daily sales uh just coupons and stuff but um below that is's
00:17:21.439 user user profiles and accounting that's where we keep all user payments and transactions as well as credit cards um
00:17:29.039 um then on the right there's a checkout module which has card order checkout
00:17:34.440 line items and other things at the bottom we have seller payouts which is
00:17:39.799 uh basically counts for the sellers that trade we have to transfer the money and collect tax and of course uh the seller
00:17:47.360 payout communicates to the store maybe saves the sales data or Gates create
00:17:53.360 reports and so on so this is kind of a very high level U um picture but
00:17:58.480 honestly it contains majority of the components to build uh a Commerce Marketplace because this diagram comes
00:18:05.520 from a real Marketplace so um real briefly I'm just
00:18:10.640 going to scroll you through so you can get a sense of what's inside of each of these so user data and payment data
00:18:17.400 product catalog has you know product variants and so on Marketplace stores
00:18:22.440 have like stores or States so profiles and so on then check out module has all
00:18:28.799 ERS line items it has cart um it has shipments stacking and so
00:18:34.480 on and then salary accounts they have various accounts with different banks how they get money we have um a history
00:18:42.159 table that we keep on and so on and uh voila this is the whole schema
00:18:48.960 of the entire thing and um when I said that we got this separation by looking
00:18:54.960 at the tables um I did not like we actually did that because we we know you can often look at just
00:19:01.919 number of foreign keys and you can sort of uh figure out by that and how things
00:19:06.960 relate but uh yeah that was a good exercise so what did we learn in most
00:19:12.440 domains it's not difficult to learn um how the data model can aggregate into
00:19:18.720 modules um the order model for example um probably needs to be in the same
00:19:24.480 module as shopping cart Lan item and fulfillment because they're all interacting together
00:19:30.200 but check out module does not need to know necessarily what it's checking out maybe polymorphic table called clles can
00:19:37.159 Define what models can be check out and how and non product is a model from another module but it appears in a
00:19:43.440 checkout module as a data object um not as a product that was kind of related to
00:19:49.080 what you were earlier saying uh you wrap active record object because you don't want to give access to another module at
00:19:55.799 the database level and this is crucial necessary separation and has to be enforced somehow because a checkout
00:20:03.039 module has direct access to the product moral uh we lose that separation so what options do we have
00:20:09.480 for loose coupling in rails apps uh we have pack work we have rails engines um
00:20:15.760 we use them in the past uh they don't have really good boundary enforcement um there's rubby gems ruby
00:20:23.559 gems are great for libraries s CI tools um plugins um it's most appropriate when
00:20:30.320 you depend down on a gem and the gem doesn't need to coll out up to the application layer uh that way you can
00:20:37.679 extract something to very self-contained unit run tests really fast enjoy all that and publish a gem and maybe even
00:20:44.400 make it open source maybe someone will use it um and um next we're going to look at
00:20:52.400 pwor and packwork is uh probably the best solution today which is why I left
00:20:58.799 to the end um for doing uh what we talked about backwork is Gem written by
00:21:05.720 Shopify and it's written to enforce boundaries and modularize rails application and it's opinionated G um it
00:21:13.480 can be used to combine groups of files into the packaging Define package level constant visibility say have publicly
00:21:20.520 accessible constants help existing code bases to become a modular without obstructing development that's really
00:21:27.320 critical and um for the next three slides I'm going to um have this uh
00:21:33.120 Source at the bottom this is coming from a really amazing talk by Mark rolds at Rocky Mountain Ruby um I I just didn't
00:21:41.679 feel like I could do better job explaining this he did a fantastic job I highly recommend that you uh write down
00:21:47.600 that URL and look look at it um it's a great 30 minute talk on packwork specifically on how they moved all of
00:21:54.400 their code into uh that what issues they run into but um here what is shown is
00:22:00.919 that instead of app um typical rails app folder we're moving towards PS folder
00:22:07.039 ining sales module reviews module and social and each module has an app folder
00:22:12.240 that has you know your standard model use controllers but also a public directory and only public directory
00:22:18.799 should contain anything that other modules talk to that's how uh that how
00:22:24.640 that sort of relationship is enforced um so here's an example um of a
00:22:31.480 violation where um a review class um directly access a sale um active record
00:22:39.200 module model and so when you run back for chip it will tell you that you have a
00:22:46.760 validation that something is accessing it shouldn't and that is the biggest value out of this Gem and obviously you
00:22:53.240 would want to run it on CI like once you do it and the thing the cool thing about it is that you can create a tiny module
00:22:59.840 and move just one file there and start creating these dependency sort of
00:23:06.360 configurations and have this pass and then incrementally just keep adding stuff to it and make sure this continues
00:23:13.919 passing um you don't need to move everything into the project folders
00:23:19.159 right away incremental ability to L this incrementally I think is what makes pwor
00:23:24.799 particularly attractive so um this um this comes also
00:23:31.159 from a talk um how to integrate PW um uh figure out what you have first move Cod
00:23:38.279 into packages declare package dependencies open public interfaces and create data objects document public
00:23:44.600 interfaces and the side code owners maintain and grow that's the Hope
00:23:51.200 what about inversion of control um well um if you have um a
00:23:57.080 public interface for module uh it's sort of uh sorry this is a facade pattern not in versional control
00:24:03.520 um facade is B basically what you would put in your public folder you know you can have multiple facades there you can
00:24:10.000 have one facade um probably multiple I'm guessing but uh it's essentially what
00:24:16.320 you talk to instead of talking to things inside the module you just talk to that facad uh and yeah it typically wraps
00:24:24.799 active record objects into some sort of hash and returns that
00:24:29.960 um and dependency inversion um is another kind of tool we have um that uh
00:24:36.559 basically what you can do is you can pass to check out uh injector basically you can inject data into checkout method
00:24:43.559 without providing direct access to the product model like I said earlier so what are the key
00:24:50.000 takeways Loosely coupled modular design does not appear out of the blue or accidentally it is an answer to a
00:24:56.679 problem of ever growing spaghetti code base um and modular design is necessity
00:25:04.279 for larger teams with 100 plus Engineers working on monolithic codebase some
00:25:09.399 companies will stall at much smaller numbers loose coupling design encourages
00:25:15.520 Engineers to think in terms of components in their module and their public apis and use existing or
00:25:22.159 negotiate new apis with the owners of other modules the ownership of the module is something I haven't talked
00:25:27.559 about but that's also also built into pord this means a good chance of doing it right without adding uh any new
00:25:34.600 technical data PW perhaps offers the most flexible incremental well traveled
00:25:40.080 path to modularity for any rubby code base um and it's the only tool currently used
00:25:47.559 in production by Shopify and many others in the end we can hopefully all
00:25:54.399 enure Los the couple Cod bases speed up their velocity and stick that
00:26:00.600 that's all we have time for today for me any
00:26:19.399 questions um are you guys using pack works at Academia no R not not yet
00:26:28.720 want to what are your thoughts on which is
00:26:34.760 similar in design with its slices as to what P does I haven't looked at Hanami as a
00:26:41.799 packwork replacement um it does it have a gy that does that as part of it
00:26:47.000 because Hanami relies on dryer B I think it's like built into the Hanami thing is this how you separated for everything
00:26:54.679 interesting that might be another option but honestly you know if if you have a rails application that's been in
00:27:00.880 development for 10 years Hanami may not be the answer
00:27:07.559 else how do you think how do you think about umor hello um how do you think
00:27:14.520 about the value of splitting code out of a rails monolith versus putting it into
00:27:20.559 a packwork module um that's a great question um
00:27:30.279 I think um that having been large companies um coinbase several others uh
00:27:38.880 most of these guys move to a concept of a monor repo uh which is where they put
00:27:43.960 everything in a single reer and have a build system build it all so I don't
00:27:49.360 think that we should be going in the splitting repo Direction I think we
00:27:54.480 should be splitting things within the repo but effectively in with
00:28:00.279 enforcement and I think that'll allow us to grow monolith through much larger size
00:28:06.159 size any more questions or last
00:28:12.240 one all right thank you very
00:28:22.080 much thanks that was great Chris getting
00:28:27.120 set up
00:28:33.080 you're morning wake
00:28:44.399 up um that's that's the the company that
00:28:49.440 your talk is based on half 100 Juniors um no we don't even have 100
00:28:56.559 employees what what did they
00:29:05.080 do don't have ni that's refreshing so we
00:29:10.120 we have nice diversity which
00:29:15.799 are together only okay um yeah hello
00:29:21.720 everybody thank you for your for giving me the opportunity here to share this story um it's one that I find really
00:29:28.120 interesting and pretty fun to learn about uh so yeah without further Ado this is how to translate your rails app
00:29:34.640 into Over 20 Languages um and why you should uh so first off who who am I my
00:29:41.720 name is Chris F like you're GNA introduce me as um you can find me on Blue Sky at Argonaut also on masteron
00:29:49.240 ruby. social I've been doing Ruby and rails for over 10 years at this point um
00:29:54.880 and currently I am a staff software engineer at bint and what is benty just to give you a
00:30:01.200 quick rundown we're a mission driven SAS company that believes every child deserves a loving family um we our
00:30:07.760 software is used by foster agencies to help them optimize and save time and uh
00:30:14.559 reduce cycle time and all that for their social workers who are out in the field working with um children who need to be
00:30:20.480 placed with foster homes and making sure that they're having like a safe and loving and supportive environment in
00:30:26.279 those homes um we're in and over 500 agencies Across the Nation uh 34 states
00:30:31.919 plus DC and they have over 150,000 children in
00:30:37.320 care uh so this talk is about localization and how we localized our UI
00:30:42.640 into Over 20 Languages but um what is localization first off and why should you care about
00:30:48.760 it so here's some definitions here um the first one l10n or localization
00:30:55.240 you'll often see these words abbreviated with number um means to adapt content from one local
00:31:01.720 into another so the classic example is what you might call translation which is when we take text from a language like
00:31:08.279 hello and English here and we turn it into Portuguese so it says Ola instead
00:31:13.679 um but localization also applies to other forms of data so like dates are a good example we write dates in one way
00:31:19.799 here in the US but in other parts of the world like in the UK they write them a different way so that's also a form of
00:31:26.799 localization um and when I say local so a local is an identifier basically that just represents a language optionally
00:31:34.200 with a region and a script attached so I have some examples here uh en just means
00:31:40.039 English uh pt-p stands for Portuguese as it's spoken in Brazil and then the last
00:31:46.919 one there is uh Chinese written in Han traditional characters as spoken in Hong
00:31:53.320 Kong so these can get really specific really down to like uh details about the
00:31:59.039 language and who speaks it and where they are um and then finally internalizations this is the last one
00:32:05.000 here it means to adapt software so it can easily support many different languages scripts regions and cultures
00:32:12.679 and so the idea is internationalization is what we as devs do to a product you
00:32:17.919 make a product internationalized and that allows you to localize it multiple times from your Source language into
00:32:25.760 whatever targets you want so uh that's all well and good right but
00:32:31.679 why should you care um don't me most people speak English right like isn't that just
00:32:37.519 enough well I mean I wouldn't be here if that was that that was true right so um just show hands who speaks
00:32:45.240 English as a second language here okay cool cool um how about who
00:32:53.039 knows someone who speaks English as a second language I think that should be everyone
00:32:58.200 yeah right um so worldwide there's 1.5 billion English speakers but there are 8
00:33:05.240 billion people in the world so that's when you think about it that's like 6.5 billion people for whom English is not
00:33:11.240 their first language and even in the US like if you look at the US Census Data there are 21.7% of people who speak an a
00:33:19.840 language other than English at home and 8.2% of us residents say they
00:33:26.720 speak English less very well and so that's all to say that like English is not enough for your
00:33:33.360 application if you really want to grow like you might default to English and it's a good place to start but even in
00:33:39.000 the US English is not enough if you want to reach the most people uh especially people who may have been underserved or
00:33:46.279 excluded from technology due to their
00:33:51.440 language okay so um let's say you have a rails app and you decided you want to localize that's great yeah yeah uh what
00:33:58.639 do you need to do so um here's your road map you have five steps um first you
00:34:04.039 have to externalize all your text then you'll choose your target locals then translate uh commit and push
00:34:12.839 and then uh just re the profits I guess um so step one is to externalize
00:34:19.560 your strings and there's a lot more to externalizing that what I can cover here uh but the basic idea is you have to
00:34:26.639 look throughout your app to find hardcoded text anywhere that it might appear to a user and so this is like
00:34:33.679 obvious stuff like in your view templates for example like here we have a an H1 tag and it says edit user um but
00:34:40.480 you can also look in controllers like flash messages are a very common place that text um user-facing text gets
00:34:47.520 generated inside of controller but you also have stuff like in your models where you might have a validation
00:34:53.240 message or an error message that gets generated and that also gets shown to a user and we need to extract the text because
00:35:00.480 as it is right like there's no way this text could change like if I want to uh
00:35:06.440 show the app in Portuguese or if I want to show it in Chinese like this text is in English it's in the source code it
00:35:12.440 can't change so once you've identified some hardcoded text The Next Step you have to
00:35:18.960 actually extract it and uh by default rails uses yl files to store strings and
00:35:24.640 it'll even generate an .o file for you when um you start a new app so you just
00:35:31.200 open that up and then you take your strings that you identified in the previous step and give each one of them
00:35:36.599 a unique key so here like we've given our edit user message the users edit
00:35:43.240 title key and we gave that flash message flash saave um and so the idea here is that
00:35:50.920 the keys will remain the same when we translate this file into other languages but then the messages will all get
00:35:56.680 translated into whatever Target local so finally once you've got those
00:36:03.119 extracted then we can go back to the original place and just replace the text with
00:36:08.160 I.T or one of its variants there's a couple different ways to call iatn
00:36:14.240 depending on where you are so um and the benefit here is like
00:36:19.839 now when this code runs uh iatn will look up the key it'll go to the local
00:36:25.400 file matching the current local take out the right message and show to the user so now this makes the app
00:36:31.880 internationalized because we can change the local at runtime and the all the text will change and all it'll all get
00:36:41.280 updated so um step two is to choose your target locals and this will vary
00:36:46.760 depending on the particulars of your situation uh but a good place to start is with these three questions here so
00:36:53.839 what are your company's goals uh what are your most important markets and who is your company trying to
00:37:01.119 reach so if you're a global product you can start by looking at what regions
00:37:06.400 you're targeting um and find out what is the most spoken languages in those regions so a good resource for this is
00:37:13.640 ethnog which I just have up here this is just a screenshot of their homepage um they have stats on language use across
00:37:20.040 the entire world for every country every region that you might want you can also just look this up on Wikipedia that's
00:37:26.160 also um relatively easy to
00:37:35.200 do um and if your main Market is in the US though like it is for usti um you can
00:37:41.200 look at the US Census Data instead um and the Us sensus website is actually really great uh it lets you you can
00:37:47.920 segment the data based on uh state or just Nationwide and they let you see all
00:37:53.079 these different combinations of the data to like uh derive different insights um
00:37:59.079 specifically the one I have highlighted here uh shows the um number of
00:38:05.760 respondents who say they uh speak a given language um and then uh breaks it
00:38:13.480 out based on whether they say they speak English very well or they speak English less than very well um and so this helps
00:38:19.560 like us to identify who might be best served by a localized app experience
00:38:25.640 because we can see like um those what those 258,000 people who speak French
00:38:33.920 and they say they speak English lesson very well they'd be really helped by having a French version of an
00:38:42.200 app um so once you know which languages you want to Target so you have to convert those languages into local codes
00:38:49.079 um these are those identifiers I mentioned earlier uh there's a lot of ways to do this again like I like using this tool
00:38:55.760 that I have linked up here you can also so again just like Google the language on Wikipedia it usually has the code
00:39:01.680 there in the sidebar um and then so once you found
00:39:06.920 the codes there's also a couple different formats for the codes if you're not sure which format you want to use I just recommend you stick to the
00:39:14.359 language tag format which uses dashes there but there's also the gnu format
00:39:19.560 which uses an underscore there's no real like benefit to either one um the main thing is just like if you have another
00:39:25.960 tool in your stack that uses or is like as local aware it's good to keep your codes and formats all consistent just so
00:39:33.240 you don't have to like convert back and forth okay so step three is translate
00:39:40.599 and this is the fun part and again depending on how your company like how big your company is your company size
00:39:46.960 how you approach this might differ um so if you're a little bit bigger uh you might contract with a language services
00:39:52.920 provider or LSP which can help you obtain professional translations from professional
00:39:58.720 translators and this might be important to you if uh Precision is really important in your company or if you're
00:40:05.359 in a highly regulated industry um with a lot of jargon or even if you're just
00:40:10.640 like you just have customers and they're like really critical of what your app looks like uh having professional translations
00:40:17.920 uh might be important if you're a little smaller um
00:40:23.520 you might consider AI powered machine translation instead uh it's relatively easy to get started and um
00:40:29.920 you can do a DIY with uh this ITN tasks gem which gives you access to uh open AI
00:40:36.720 Google DL a bunch of different providers um and if you want to something a little
00:40:41.800 bit more off the shelf you can use a localization platform like one of these I listed up
00:40:50.319 here but for now let's say we want to go the DIY route um because yeah it's pretty easy and lets you get going fast
00:40:58.000 so uh let's set up iatn tasks it's just a gem you can add it to your gem file um
00:41:03.839 and then you have to choose a translation provider so for example like Google Translate for example you get an
00:41:10.040 API key for your provider um and then I tasks it uses environment variables to
00:41:16.000 configure so the uh it wants the Google translate API key and this Google
00:41:21.359 translate API key environment variable so let's put it there and then finally you can run this trans missing command
00:41:28.640 um that I have up here on screen this will basically take all of your English text and then translate it into all of
00:41:36.160 the different locals using whatever provider you selected and in the end you'll end up with uh one yaml file for
00:41:43.920 each of your target locals so now it's time once you got all
00:41:50.319 those files generated now you can commit and push but uh watch out because the local files can be pretty large and you
00:41:57.440 might run into some problems uh for example GitHub could reject your push if it's too big this is actually a thing
00:42:04.400 that happened to me when I was uh doing this at binty um my I had to split up my
00:42:09.760 PR into one commit for every language because the the commits were just too big um the extra files could add bloat
00:42:17.680 which may make like cloning your repo slower or make your repo your repo source code take out more more disk
00:42:24.720 space on whatever like provider uh wherever you deploy to all of those
00:42:30.000 extra string objects they could lead to increased memory usage at runtime um and they could also lead to increased asset
00:42:36.720 size if you do something like bundle your translations into your JavaScript
00:42:41.880 for your front end um these are all just like potential problems that you want to look out for
00:42:48.200 so you can have like you should have monitoring or some sort of alerts to like alert you if something's going
00:42:54.280 wrong um but assuming nothing is congrats that's all you need to do your
00:42:59.400 app is translated uh but wait um you're not really done because that's just the
00:43:05.000 beginning there's a whole lot more to internationalization than just translating text um and to give you a
00:43:12.079 taste here's like three things that uh we at binty were looking at next after
00:43:17.440 doing this initial translation push um so localized formatting is the top one
00:43:23.280 uh this is like I said before dates numbers um even calendars like how a
00:43:28.319 calendar is laid out and what the months are called and how how you name the days
00:43:33.559 those all vary based on region B based on language um plural rules so stuff like
00:43:40.160 if you have a phrase like n applications were updated the the phrase changes
00:43:45.200 based on how many what nend is if it's one or two or whatever um English we
00:43:50.559 just have single and plural but um other languages may have more or less
00:43:55.839 categories um and the last one here is continuous localization which basically just means
00:44:02.240 automate everything I've just been talking about which is really like a lot harder than it actually
00:44:10.000 sounds okay um so this talk is based on bent's experience translating our app
00:44:15.880 into 21 different languages hence the title um and I just wanted to wrap this up by sharing a little story about our
00:44:22.160 journey at bti and um what we learned so uh part of P's mission is
00:44:28.319 helping foster agencies with who are our customers reach more families so they can find more Caregivers for children in
00:44:35.359 need and U many of these potential caregivers are older less familiar with
00:44:41.119 technology less comfortable with English and so even though we only really have us customers localization and
00:44:47.960 internationalization were still a very important thing for us um so when we started we had uh English and then
00:44:54.920 manually translated Spanish just basically based by um Spanish speakers who are
00:45:01.040 employees um we used the US Census Data to uh identify 19 new languages the list
00:45:07.520 is there on the screen and this covered about 65% of the uh less than very well
00:45:14.079 English speakers um and then we translated using I tasks and the Google translate
00:45:21.160 API uh and yeah and along the way we learned a lot about multilingual text
00:45:26.359 and UI uh so the first learning that I wanted to share is just about multilingual
00:45:33.079 fonts um so you probably use a custom font in your application um but what you
00:45:38.680 might not know is that not all fonts support um non-latin scripts like cik or
00:45:45.319 Greek and when a browser encounters text that is not supported by the current
00:45:50.440 font it'll fall back to the system font and so in B's case we noticed that the fallback was sometimes inconsist
00:45:58.079 like it would be a sah font when our uh our main font was a s sah font and
00:46:06.200 so yeah so it ended up being because we weren't we weren't consistently specifying at the base of our font stack
00:46:13.200 uh siif or S serif and so that's the learning here like always be consistent
00:46:18.440 and have serif or S serif at the base of your font stack so that the browser will be able to choose a visually consistent
00:46:26.720 uh font to match like the rest of your app um and by the way if you're using
00:46:33.359 Tailwind which um many people probably are maybe uh you're probably already
00:46:39.040 covered because the inter font that Tailwind uses by default uh includes celic and Greek which is like a a great
00:46:49.200 start um the second is bir directional text uh also right called right to left
00:46:56.119 um some Scripts like Arabic or Hebrew they flow right to left across the street and you might think that that's
00:47:03.280 just about text but it's really about like way more than just the text and there's a lot of like unexpected um
00:47:10.839 impacts on your apps UI and the ux of your app so some interesting stuff here
00:47:15.920 is like three highlighted in that screenshot the button order like the primary button has should be on the
00:47:23.359 right uh of a list of buttons first whereas in like English it might be on the left U check
00:47:30.760 boxes and icons usually appear on the right verses like on the left um and
00:47:36.920 what was most surprising to me progress bars they fill from the right to the
00:47:42.880 left so like zero is on the right versus and 100 is on the left which is like
00:47:48.920 backwards and so the learning here is RTL is about a way more than just text
00:47:54.000 like you can translate to the text but like in impacts the entire UI and ux of your
00:48:01.440 application um and so the last topic I have here is about local names and this
00:48:06.559 is like super um super surprising to me when we when we discovered it so like it
00:48:13.440 might seem simple right like you could you should just be able to write the local names in English and translate
00:48:18.720 them into other languages and that should be fine like right you would think that' be true but actually
00:48:24.119 different languages and different regions have different uh formats for how they name other
00:48:29.839 languages so like in English we might say Canadian French but in German
00:48:35.839 actually it's um I'm not going to try to pronounce German but French and then
00:48:41.359 Canada in parenthesis and it's supposed to be in parenthesis um and so the learning here
00:48:47.599 is like don't machine translate these um we ended up leveraging data from the
00:48:53.960 Unicode common local data Repository which is a standardized set of uh data
00:49:00.880 files that have all sorts of data about languages across the world and um we used that data to help build this um
00:49:07.880 language selector that you see on screen
00:49:12.960 here yeah okay so that's that's all I have um thank you everybody for listening um and yeah good
00:49:25.480 luck all right do I have time for questions
00:49:32.400 yeah wherever you want to start
00:49:37.680 first uh great talk Chris um I wanted to ask how do you ensure the accuracy of
00:49:43.480 Google translate because sometimes it's not always accurate yeah great question um
00:49:51.440 so right now the answer is we don't um but there is a practice called
00:49:57.079 linguistic QA um that you should like as you grow along in your journey um that's
00:50:03.200 something you can look at usually what you end up doing is you have a human who is a native speaker like edit the The
00:50:10.440 Machine's output so they can see like oh is it saying this phrase wrong I'm like
00:50:16.400 oh this is a weird way to structure this let's rewrite it so that's normally how you would approach that but we we're not
00:50:22.559 there yet
00:50:27.839 actually I have the same question so um I'll just add that I I remember hearing uh Bill Sullivan who was the global one
00:50:34.880 of the global VPS at IVM talk about this at localization world he said that it's
00:50:40.559 called Sullivan's law he said that any person's willingness to use machine translation is inversely proportional to
00:50:47.720 their knowledge of a second language that was really funny um I
00:50:53.599 guess but already answered the question so I'll hand off the microphone
00:50:58.680 yeah I think like machine translation has gotten a lot better in recent years especially with with the rise of AI but
00:51:04.400 um yeah they're they're not perfect yet definitely I have a related one actually
00:51:09.440 I can shout out so you mentioned multiple different providers did you try Google translate against an AI solution
00:51:16.160 and if so how did you find the quality difference there um yes so we did try Google translate versus open AI um like
00:51:24.599 directly and through um through Azure I think that was the only one we tried uh
00:51:30.720 just the the thing about it was like it was mostly um uh a cost thing like it was more
00:51:37.839 expensive to use open AI so um we ended up using Google translate and Google Translates translations are actually
00:51:43.880 like pretty good and you can um if you use the one from Google Cloud I think they actually incorporate some AI
00:51:50.240 functionality into the Google translate uh API there
00:51:59.079 have a kind of funny story we we used to we years ago we at we doing like a project
00:52:06.040 for eBay localization project which meant we have to translate eBay's um
00:52:13.440 items item names and so imagine there is a catalog which is huge and of course
00:52:18.960 like most of the items yeah we use Ma translation for that because it's like milons of them or like whatever and um
00:52:26.599 it but my favorite category was music so you go to music category and it tries to
00:52:32.640 translate all the band names
00:52:39.040 czy uh after the migration uh how have you prevented future impactions from in
00:52:44.400 herota base I know you mentioned automation CI just curious how you how you're thinking about that yeah that's a
00:52:50.520 great point so like definitely as you like once you translate if like your
00:52:55.599 devs are G to put more text into the app right so you have to that's why continuous localization is an important
00:53:01.040 thing and we're working towards that right now basically like um we just have to rely on somebody to like go and run
00:53:08.160 the translation again to like get everything back up to up to speed but like that's obviously not scalable and
00:53:14.000 we want to like make that faster so like continuous translation means just automating everything detecting changes
00:53:19.480 and running the translation
00:53:25.160 continuously was I just shout out I got it um so there's like the technical
00:53:30.720 piece of the translation but I'm curious um somebody emails you in a different language maybe nobody on the team knows
00:53:37.359 it um how do you deal with that is there a tool does somebody on the team know the language like how do you decide kind
00:53:42.599 of the back office stuff behind app yeah so the question is like yeah your like I
00:53:48.119 covered um your UI translation but yeah how do you do everything else like um inbound support in a different language
00:53:53.720 or or other kinds of like like receiving receiving other Communication in other languages so that's very good thing like
00:53:59.680 leveraging a localization platform like I mentioned um crow in and phrase um as
00:54:05.280 two ones that on my slides they have different Integrations with like zenes or whatever inter intercom whatever like
00:54:13.359 help desk tool you want to use and they can provide like tools for your support texts to like automatically translate
00:54:20.240 messages back and forth so that's one thing you could do um yeah I think like again like we're
00:54:26.559 we're not there yet we we do have like we want to get there because like our like our support needs to be able to
00:54:32.559 communicate with people and if we're making the app available in uh Bengali someone types in Bengali to our support
00:54:39.119 text they need to be able to understand but like that's something we're not uh we're not there
00:54:45.240 yet I just had a question about maybe like kind of more like the product Road mapping process of this because I'm
00:54:52.000 working in an app it's like 20 years old and uh we do have an international like user base but we kind of been like
00:54:59.559 scrabbling that together um but we're doing an overhaul into Flex with our UI and so we're using this as a chance to
00:55:05.200 add in those translation keys but it's kind of like a well then what is this process going to look like when we
00:55:10.280 actually go to do it so I I that's a longed way to say like were you did you have a team that was like fully focused
00:55:17.000 on this while like other teams were shipping out did was this like all all hands on debt kind of thing you could
00:55:23.160 take to that process yeah yeah good question um so so yeah so this this
00:55:28.920 whole journey that I spoke about was handled by by my team basically so was me and two other devs we were basically
00:55:34.880 taking this and a couple other related AI translation features like all at once
00:55:40.160 is like our work for basically like the summer I think it was like that we worked on it for about a quarter um and
00:55:46.760 so like yeah we were we were entirely focused on this um everyone else at our
00:55:51.799 company they were all doing their own like their own features so it was basically just and then um when we Shi
00:55:58.440 it out it's so far been working good go back behind them and sweep
00:56:04.960 up hey everybody my name is Todd um I'm with rocker Solutions it's a small
00:56:10.119 consulting firm uh two people we do Ruby on Rails Consulting uh tonight I'd like to tell you about uh the first gen that
00:56:17.119 I uh recently published it's called filter ameter and it enables uh
00:56:22.520 declarative filter parameters that make it easy to turn uh search query parameters into rail's active record uh
00:56:29.599 and so if I could share a quick couple things about it uh the first one would be that it makes your controller is very
00:56:35.240 easy to read uh you open it up and if there's a say a filter on size it literally says filter size uh the second
00:56:43.319 thing I'll tell you about it is that uh it makes writing controllers uh faster simpler um and so the development
00:56:50.559 process um is fast as well uh it really leverages active record
00:56:56.839 uh at the end it outputs active record and you can uh start with an active record as well so nothing new it's very
00:57:03.280 simple um fits in well uh and the last thing I'll tell you about it is that it plays well with others uh sometimes I
00:57:09.680 get worried when I bring a gem in like what is it doing what are the hooks has it monkey patched uh this doesn't do
00:57:15.520 anything by default you have to pull it into a controller mix it in uh if you love it you can mix it into application
00:57:21.720 controller uh and then even then you have to uh invoke it uh in order for to do anything uh so it's really easy to to
00:57:28.559 bring in and try it out uh so I'd love for you to check it out the name is filter filter ameter filter parameters
00:57:34.799 is where the name came from uh if it looks like something that might be helpful if you put a star on the repo
00:57:40.480 that helps spread the word thank you very
00:57:46.839 much okay so my my real skills are out of date but I realized that my product
00:57:52.520 management skills are still solid as I want so if any of you are looking for a
00:57:58.039 product manager especially if you've got a rails team I actually can write specifications I can write write
00:58:04.319 requirements in in in cucumber so if you're looking for a good product
00:58:09.400 manager works with a rails team on
00:58:15.920 your did you say your name I am Ken Ken awesome I did not just
00:58:23.559 want to make sure your name was out there you know um I'm Cameron Dutra work for GitHub the um only thing I wanted to
00:58:29.680 bring up today is this really cool website that I heard about at rails sorry rubycon in Chicago last week um
00:58:36.720 who knows who Marco Roth is yeah he was actually at our first meet up uh in s he
00:58:42.720 flew in from Germany um he has put together I'm gon pull my phone out what's
00:58:49.280 that oh I'm so sorry um let me just pull up the actual website here I get the
00:58:56.480 name right yes okay so he is a big conference
00:59:01.599 attender Meetup attender and he's put together a website called ruide dodev if
00:59:07.039 you haven't heard of it it's super cool he's like indexed pretty much every talk you've ever from every conference You'
00:59:13.000 ever heard of going back to like 2006 I think on this website you can go find your profile if you've been the speaker
00:59:19.119 claim it you can see all the videos you can search sort descriptions of the videos sometimes transcripts it's really
00:59:26.160 really cool so take a look at Ruby
00:59:34.160 video. to follow up on thatby video that was about to be linked from Ruby's official website uh there's a full
00:59:40.119 request open it's going to emerge very
00:59:49.400 soon hello I'm Dave I'm working with American Luigi post 599 here in San
00:59:55.039 Francisco which meets in the uh the War Memorial building which is theater and
01:00:02.319 the SP right on uh we have a monthly code of connect for veterans and Friends of veterans that meets roughly the
01:00:09.559 second Wednesday of every month and anyone who is a veteran if you know veteran if you would like to come and
01:00:16.440 help veterans it's open to the public as well the venue is fantastic and it's
01:00:22.000 very close to part hit me up afterwards I made do this again at Future meetups just to drum up
01:00:38.480 some hey my name is Brian uh based on the last talk is one to get props to the US Census Bureau they have some amazing
01:00:45.640 data um there's a gem I maintain um called USG which takes the geographic
01:00:52.280 data from the US Census Bureau and normalizes it relational data structure
01:00:57.359 to make it far more usable um it includes things like population density
01:01:02.440 housing density um we use it for things like have a zip code I can tell you the county the state the metropolitan area
01:01:09.240 the urbanized area is it Urban is it rural um so if you ever need to use any of that data it's all based on active
01:01:15.400 record but there's CSV files available download you can put them in
01:01:24.720 Excel and last four think
01:01:36.599 five okay say this is open mic so just gonna tell you uh like a DA daily basis
01:01:45.160 doation like look at I mean listen to your heart and also to your logs uh I've
01:01:51.920 been uh working a lot the last quarter trying to improve our quality of our
01:01:58.440 application in general and it's been uh interesting to learn to I mean show to
01:02:06.319 my co-workers how to read LS and what it meant of everything how to pipe them to
01:02:13.599 places to gra or create that on open tet and say
01:02:19.680 this see because you cannot just try to figure out how to improve something by saying like
01:02:26.240 no it's not better so this introdu you to some kind of a new war about the
01:02:32.480 statistics where you can tell why this changes just not because it's fast you
01:02:38.279 say because I take it well maybe there is another thing that you maybe affecting other places but you need to
01:02:45.119 know where you are doing so everything start from is
01:03:01.039 hi my name is sp at and I'm working on an open source project called U
01:03:06.520 macchiato it's at macchiato dodev and uh the first project is called
01:03:13.760 RTO and um it's not going a redesign but basically it's like a code notebook that
01:03:21.680 is like for editing markdown and part of the idea was that you could run
01:03:26.799 um code you're playing with and use it with real data and so it had a security
01:03:32.119 sandbox and the reason I'm redoing it is because the security sandbox didn't actually prevent Dex filtration if you
01:03:38.839 go to the web ACTC um CSP content security policy um page or GitHub repo
01:03:46.000 and look at issues there's some concerns about um actually preventing next filtration the uh browser security model
01:03:53.520 with not security policy is really good at keeping one have separate from the other but if you want but you can't really run un trusted code on it because
01:04:00.240 it could set up connections because the B API surface area is so huge so what
01:04:05.799 I'm doing now is I'm basically allow listing the code that runs directly in
01:04:11.000 the browser and interacts with Ain so I'm building code modules that for instance won't link you to a site so if
01:04:18.960 you use the spreadsheet mod module you allow to tell it which URLs you want to
01:04:24.160 be able to clickable when we you link them so if this sounds interesting to you uh talk to me or go to uh Mai A.D
01:04:33.119 and I'll be a link to the RJ code based there and you can check out the code and
01:04:38.880 um I'm been Atkin on GitHub and that's where um my email address is because
01:04:45.079 GitHub has the uh slightly harder to scrape email address that's like a
01:04:50.160 JavaScript gener address so
01:04:59.520 than um I this is my favorite part of this so for um so
01:05:06.520 he didn't have a chance to speak today you have the next me up remember there's
01:05:12.920 always the next one so uh Brad is Sten up
01:05:18.760 and Brad is uh the person who builds so many things
01:05:25.440 um Brad do you know I I gave a bunch of talks this year and I used Brad's first
01:05:31.599 maybe not the first but one of the early products built by Brad gester po everywhere I used it during my
01:05:39.520 presentations um it was pretty funny you can like you can um just going to use in web sockets and stuff to for Real Time
01:05:48.200 holds yeah but today um Brad um Brad is going to share some
01:05:55.680 something about um I'm talk about S I figured I
01:06:01.319 just figured I'd tail in the open mic and say if you're blue sky curious or you're on Blue Sky on the right if you
01:06:07.640 scan that QR code I've been throwing as many people who hack on Ruby as I can on there including people are presenting
01:06:14.240 tonight and then on the left if you want to see like chill Twitter vibes from say 10 or 15 years ago when the fail wheale
01:06:20.760 was a thing uh this is what it looks like we have some I don't know some Western theme bed spreads going on there
01:06:28.039 somebody's backyard there's a retro chat GPT pretty Chill Vibes I think like
01:06:33.599 what's missing from this is just like intense crazy stuff um so if you're kind
01:06:38.880 of in the mood for just kind of more of a chill Doom squirreling that feels less doomy check out Blue Sky um and also um
01:06:46.640 find me on there and tell me that you want to be on this list if you're on Blue Sky and you hack on this and last
01:06:52.160 thing you can actually set up your domain name as your username so I badger.com on there and you should get
01:06:58.000 on there hook your domain up to it and you can have any domain you want as long as it's
01:07:08.680 available all right so with that I'm going to talk about an open source
01:07:14.160 project I've been working on for quite some time now I didn't realize that until I put this together called site
01:07:19.960 press uh just a quick show of hands how many of you are using site press all
01:07:26.319 right that's fine I was asking what should I talk about for this presentation and I didn't get any responses so that's good I'm glad nobody
01:07:33.520 raise their hand because I'm going to kind of run through a intro crash course uh but I'm going to skip the basics
01:07:38.720 because that's all on the website and I'm going to run into like okay here's what kind of peak usage looks like with
01:07:43.920 site press and some of the interesting things you can do with it uh but first you need to understand what are my
01:07:49.079 motivations behind site press why did I build it uh quick show of hands who's heard of
01:07:55.119 middle all right good I got a decent starting place
01:08:00.599 so you may be familiar with this it's a static site generator um you can take a bunch of markdown files H files and
01:08:06.440 whatever and throw in a folder type compile and then it just generates an HTML site you can upload it to S3 or
01:08:13.440 what have you so I started with this in 2015 and I was pretty happy with
01:08:18.520 middleman until tried to embed it in a rails application and then I just started running into dependency hell so
01:08:25.199 this was was me actually today don't let the Amber CRT screen throw you off uh so
01:08:31.400 I'm just looking at the dependencies and if you've worked with rails for a while you'll know that these dependencies cause
01:08:38.159 problems uh so I was um defeated whenever I tried to embed middleman into
01:08:43.520 rails and I thought you know what maybe jaal will just embed in rails and guess what it also had the same dependency
01:08:50.159 hell uh so a lot of these things if you again have ever worked with rails it just doesn't work maybe it works with
01:08:56.199 rails 5 but as soon as you upgrade a rails 6 uh too bad your i8n framework uh
01:09:02.080 isn't compatible so it breaks the whole thing and it's just not pleasant so I set off to build middleman and
01:09:08.719 rails and uh my daughter is now eight so she's a lot bigger than she was in that
01:09:14.159 picture but it is actually site press code to the right uh you may recognize
01:09:19.440 til is in there it is no longer in there um it's just I'll get to that actually uh kind of a fun Journey so here's proof
01:09:26.520 in the uh commit log February of 2016 was the initial commit and site press is now over eight
01:09:33.719 years old which means that I think site press is finally good it's almost good enough I think in two more years it'll
01:09:40.120 finally be ready all right so uh on the intro slide you may have noticed that um site press
01:09:46.000 you can build ambitious content sites and rails that's kind of what I tell people to not explode their brains it
01:09:51.319 can do a lot of things it can generate static websites you can ED it in rails you can do both or you can have your cake and eat it too
01:09:59.560 and apparently when cake eats itself it has it too it enjoys A Nice Class
01:10:05.600 A all right so if you start using site press this is what it would be like if you use it as a static site generator
01:10:12.120 you install the gem you create a site you fire up the server and then you compile it you get a bunch of HTML files
01:10:17.840 just like middleman and jaal but it changes you can actually embed it in rails so in a rails application if you
01:10:24.239 run bundle ad site press rails and then you install it you will get an app content folder and I'm actually going to
01:10:30.480 do some live coding demos to kind of give you a tour of what that looks
01:10:36.880 like the other thing that you can do and I've done a lot more of this lately is you can just run site press as a
01:10:43.280 standalone server because I'm going to let you in on a little secret here site press it's just a teeny tiny
01:10:50.400 rail server so if you look at the screen here on line 11 you can see that site press
01:10:56.159 server just inherits the rails application server I did this entirely by accident I
01:11:02.360 want to say about three years ago this happened when I realized that oh wait I don't have to maintain all this web
01:11:07.679 stuff I can just let rails do that I can kind of ride on their shoulders and then I can just delete a ton of code um and
01:11:13.840 it's awesome because rails 8 comes out and I get all the performance benefits and all sorts of stuff uh which Speaking
01:11:20.040 of performance I built site press do you get a Content website working at pole everywhere
01:11:25.800 um I was at fly for about two years and one of the first projects I did there is they had a middleman instance and it was
01:11:31.840 something like a thousand pages of documentation that took about 10 minutes to build so I said you know what just for fun I'm going to try moving all that
01:11:38.159 middleman stuff over into Cypress and it brought the build down to 30 seconds so
01:11:43.800 thousands of pages compiled in about 30 seconds and I didn't even do anything special with the compiler it just page
01:11:50.480 after page serial there's no concurrency I'm not hitting multiple CPUs was a will crank out thousands of pages in 30
01:11:58.600 seconds so I figure if I ever need to compile tens of thousands or hundreds of thousands of pages maybe I'll look into
01:12:05.840 uh running that across multiple CPUs all right so a lot of websites has
01:12:11.600 used it but the one that I want to show you today is mine I gave a presentation on this I
01:12:16.920 think two meetups ago um but lately for the past month I've been working on documentation because if you're building
01:12:23.159 a tool for developers developers like really good documentation and so of course I reached
01:12:29.440 for site press to build that and now I'm going to jump into a demo and we'll see if I can do this onehanded while holding
01:12:35.840 a microphone all right someone to hold the mic yeah I'll
01:12:41.360 see if it works but thanks for the offer I might take you up on that I would
01:12:46.840 do no that's what I heard all right we all heard
01:12:52.000 that so hopefully I have the server running here yeah all right uh and I'm
01:12:58.280 going to zoom in a
01:13:03.520 bit all right so these are the documents on uh terminal wire I call them manuals
01:13:09.480 and Licensing I'm kind of playing around with going to old school on this um and you know what instead of docs let's call
01:13:15.239 it manuals instead of pricing let's call it licensing so I thought it' be kind of cool manuals are these like books right
01:13:21.600 and books have chapters in them so let's take a look at the rubyan rails documentation you can see we have chapters sessions we
01:13:28.679 have all these chapters over here there's a cover if I actually click on the cover kind of have this like landing
01:13:35.159 page type thing here and we can see the content table of contents so on and so
01:13:40.440 forth so what does this actually look like in site press and I'm going to
01:13:45.600 start first with the content but one thing I like about site press is it's not mystery of where is the content um I
01:13:53.040 can see the URL here it says doc so I know that I'm going to have a file in my rails application um I should see
01:14:01.600 if I can crank the resolution up here so you can see this a little bit better no it's too L I'm just gonna kind
01:14:08.800 of we out all right so we have a than all right so we have a folder called app
01:14:14.000 content and content is kind of where everything lives here we have pages so if I go into docs and rails uh we can
01:14:21.760 see here uh we have the mark file the title The subtitle all that stuff so let's say
01:14:27.800 that nobody knows what rubyan rails is but they know what rails is so we change that hit refresh and you can see how
01:14:34.560 everything updates so that's starting with the content now we have the content which is
01:14:40.440 a bunch of files and I have these things called page models so this kind of gets into some of the more advanced uh use
01:14:46.719 cases with um with site press so we have a manual page and this is kind of like
01:14:52.920 the cover right so think of this as just a manual a manual has a title we have the CSS classes and those are pulled in
01:15:00.239 you could almost think of this as like an active record model for content and the thing that I care about the most is
01:15:05.360 that manual has many chapters and so we're creating these instances of chapter pages and this is what a chapter
01:15:12.560 page looks like so we have a chapter number we have the manual which is the the parent page and then of course uh we
01:15:20.360 have a title and a subtitle and then if we actually look at a view so similar to rails we have a
01:15:27.080 model it has a view so let's open a manual view this might look a little crazy
01:15:32.600 because it's all done in Flex I don't use any earb in my projects anymore or H or any of that it's just all flex but
01:15:38.960 you'll see here that um I grab the manual create an instance of the manual and then I can call that from here and I
01:15:44.639 can say hey let's pull the CSS class here's the manual title and then here's
01:15:49.840 the first chapter and then we want to render the cover and then this is the table of contents
01:15:55.520 so we see here we have that and we say hey give me all the chapters and you can look through that just like you do an
01:16:01.080 active record model all right so I have this checklist
01:16:07.199 here to make sure I've covered everything and oh the last one I know I forget headless CNS by a terminal wire
01:16:14.600 CLI so you've probably heard of like headless content Management Systems where they'll Expos the stuff as like a
01:16:20.159 Json API I kind of compare that to service oriented architecture like why would you want to have an API between
01:16:26.600 yourself and a content and HTTP just just call a model in memory uh so if I
01:16:33.800 open up the manual application terminal you can see here I have this model and I say hey give me all the
01:16:40.560 manuals and want that
01:16:49.800 canand all right so these are all the manuals
01:16:54.960 make it bigger and then just for fun let's read the rails manual and we'll see all that markdown content uh be
01:17:01.600 emitted into the CLI and all that is streamed over terminal wire so there's no apis involved here it just streams the
01:17:08.040 standard IO from this uh terminal and you can see I run it through this tool that converts the
01:17:14.400 markdown for my manual into something that the terminal can understand and then I Adit it to the screen and I scream it over web sockets to the client
01:17:27.920 thanks all right so that's it for the demo I'm going to
01:17:33.880 hit on a few future site press things that I've just kind of thought about doing this and working with this for the
01:17:39.120 past eight years um if anybody knows Joel Draper he works on Flex he's infected my mind with flex and now I see
01:17:46.440 the entire world is flex so site clex is something that I think would be fun um if you've worked with markdown you've
01:17:52.560 probably thought o it'd be nice if we could have like multiple blocks and not just this one block that we call Body I
01:17:58.280 think this could accomplish that the SX highlighting looks pretty nice here and um if there's if you're using her dots
01:18:05.280 and the right like Zed you'll have snx highlighting if you're embedding markdown inside your Ruby so this is
01:18:11.520 something I'm playing with I'm not quite sure how these pieces fit together yet um but I have some ideas on how to get
01:18:17.639 this put together uh the other thing I want to clean up are the page models um it was a
01:18:23.520 lot of code that you saw when showing the page models of the manual and the chapters I think that could be cleaned
01:18:28.880 up with active models so you could say a Blog has many posts a manual has many chapters so something like that that
01:18:35.760 looks a lot like active model working with content uh this one's easy I have a PR
01:18:42.000 open for it but if you look deep down the way the pages render are kind of crazy so I can kind of self-contain that
01:18:48.159 in a page and a page could tell rails hey here's how you should render me I marked down I have something else
01:18:55.199 um there's some helpers that I can improve in the uh page URL and uh that's kind of it for the the future uh things
01:19:02.760 that I would do uh for site press I did miss another thing that I worked on
01:19:07.880 maybe it'll be a different time because we were running short on time um but I I
01:19:13.040 do maintain another gem called Mark down- rails um and if you have a d html.
01:19:18.960 MD file on your rails application it'll render that and you can actually edit that template Handler during your uh
01:19:25.360 development environment just refresh the page and it'll update you don't have to restart the server do anything like that
01:19:31.360 and you can even run like five different flavors of markdown in one rails application if you
01:19:37.239 want maybe another uh maybe another day but uh if you scan that QR code you
01:19:43.360 can get the slides and then there's all that fun stuff on the side if you want the links it's all with that code any
01:19:49.040 questions I have questions yeah did you ever get to the bottom of why middleman was so slow at fly uh I didn't dig too
01:19:57.040 deep um when I when I dug into it I think what I was doing is rendering the
01:20:03.080 HTML as a giant string and then kind of for each middleware that it has I would just like try to parse the entire page
01:20:09.440 as one string and then make changes um so like if there was um like an image
01:20:14.880 asset helper um it would have to like essentially go through HTML and find whatever it is it's looking for um
01:20:21.560 whereas rails it's just calling like Erb or is calling it like one way through
01:20:26.639 its um rendering engine and spitting it out that's the kind of the the best I came to I did look at the um like why
01:20:33.880 was the concurrency thing so slow and I just couldn't really work that out um I'm also just not that great whenever it
01:20:39.199 comes with like concurrency and Ruby
01:20:45.360 y so would it be fair to say that you cut out the middl
01:20:53.159 Mance wow I like a good pun who can top that
01:20:58.639 pun I'm sorry I don't actually have a question I just was going to say that that was good like say that it's like
01:21:06.320 you take work press and yeah I think um site press is an
01:21:12.840 adobe trademark thing I haven't heard from also the oh if if anybody goes to
01:21:18.280 site glass coincidence right yeah of course well actually do have a question though what is uh I I looked at the code
01:21:25.760 already and uh there's a site press rails gym and a site press core gym does that mean that it can run without
01:21:32.480 rails or um is that like or is a core like the CLI or something how the structure yeah uh good eye so yeah
01:21:41.360 technically you could run core without rails um that's really kind of a relic from before when I was looking at
01:21:48.120 middleman and Jackal and it's like oh they run without rails and all these web Frameworks um but I did realize like oh
01:21:56.080 actually it's kind of nice just to I don't have to deal with all the web stuff like I just let rails deal with
01:22:01.199 that U but that said like um so the right press core does deal with traversal so if you say like current
01:22:07.360 page. children. parent it will deal with all that stuff so I think in theory you could take core and point out a
01:22:13.239 directory and Traverse it um using just cite press core without needing a
01:22:18.679 Cypress rails so where you might um wind up at would would it be possible that you might wind up with uh dependent on
01:22:24.920 some of the Rails gems but not depending on the entire
01:22:30.120 rails yeah so if I skip back to the uh to this slide you can see um on lines
01:22:37.000 one two and three those are my requirements um two the um sprockets rail tie like you don't really need that
01:22:43.360 it should be prop shift um but really I'm just using the only dependencies I'm using from rails is um action control or
01:22:50.880 rail tie and of course like that ties in a bunch of stuff like active support and like lots of other stuff so it's it's
01:22:57.159 pretty big but I found that if you're working with a lot of reals applications um and you just want to view everything
01:23:02.600 in the world as flex and rails as I do like I have a hammer so everything's a nail um it works for me but yeah it
01:23:10.159 won't work for other people who are just working outside of rails um you could use site press core but this is really
01:23:15.520 kind of built for um people who are just familiar with rails productive in rails and and uh you know want to use that but
01:23:23.040 you can run it Standalone and just not even know that rails is is running underneath it but it also does work with
01:23:29.360 like a lot of rails plugins so that's kind of another benefit you can just technically throw a rails plugin in
01:23:34.760 there and it'll kind of work it takes some effort but um this has access to the whole rails plugin
01:23:44.120 ecoystem yeah eight years later how does this compar to
01:23:49.960 Bridgetown um I haven't done a side by side with Bridgetown but I have had a few people tell me it's faster that's it
01:23:57.000 um yeah I know Jeremy I can't remember his last name um has worked with Bridgetown and they're doing some
01:24:02.639 interesting things to it but I don't know how or why it was faster it could be the person that was using it just
01:24:08.480 wasn't holding it right I don't know but that's kind of all they heard about it um I talked to Jeremy a bit a while back
01:24:16.600 I forget what we were talking about maybe like using cpress core to handle the pat traversal and stuff and plugins
01:24:22.400 but um I haven't done like really a side by-side comparison the only like I've only been
01:24:27.920 deep on middleman and Cypress I know middleman just has way too much going
01:24:33.000 on any other questions all
01:24:45.800 right
01:24:50.840 HD all right so they bread great presentation um two of them or three of
01:24:58.000 them okay yeah um Jeremy is setting up I
01:25:03.400 I gotta make a short intro here Jeremy Evans um for me is the legendary
01:25:12.320 ruist and at evil Mars when we recommend books to for kind some sort of advanced
01:25:20.159 uh rubyist we recommend polished Ruby programming by jerem
01:25:25.800 Evans
01:25:31.280 um so this is a huge honor to have you today with all of us to share um and I
01:25:38.320 think it's it's going to be super interesting for many who've never maybe used um um I don't know um Roda I think
01:25:47.920 more people probably used uh seel um so but I think
01:25:54.760 all of us want to learn from you from joury regardless if we used if we could
01:26:01.320 use directly uh germ projects or not it's just that it's a amazing um example
01:26:10.719 of building high quality software thank you thank you very
01:26:18.719 much I'm super happy to be here talk to you all I'm honored that you asked me to come present
01:26:24.840 uh talk about Roa so Roa is a web toolkit that I launched in 2014 so I'm going to go over in this
01:26:31.840 presentation go over my background a little bit I'll walk through a brief example using Roa discuss roa's goals
01:26:38.080 and how it achieves them uh examine the progress made in the last 10 years since roa's launch and then I'll show how some
01:26:44.920 open source software uses Roa my name is jemy Evans uh this is my first time
01:26:50.159 attending the San Francisco Bay Area rby Meetup I'm hoping to be able to make it down here for future meetups uh I live
01:26:56.000 in Sacramento so I'm not not too far away uh I've been using Ruby for almost 20 years I think I was originally
01:27:02.880 introduced to Ruby in December 2004 and it quickly became my favorite programming language I maintain Roa and
01:27:09.119 many other Ruby libraries such as SQL rodo tilt rack test e- Ruby warning and
01:27:16.280 Min test hooks I'd say almost all ruby web applications depending on at least one of these libraries probably either
01:27:22.800 tilt e Ruby or rack test I'm one of the maintainers of rack and almost all ruby
01:27:28.880 web applications are going to depend on rack I'm Ruby committer I was the primary implementer of keyword argument
01:27:35.159 separation in Ruby 3 uh you saw the code example in uh the site press
01:27:41.800 presentation by Brad uh I also implemented the um keyword the anonymous
01:27:47.719 Splat in keyword spot forwarding that was he was showing in his his example uh these days most of my work in Ruby
01:27:54.280 itself involves on fixing bugs and Ruby uh in a lot of cases those are bugs I introduced in the first
01:28:00.520 place I am the author of Polish riew programming which was published a few years ago so this book is aimed at
01:28:06.119 intermediate Rie programmers and it focuses on teaching principles of riew programming as well as trade-offs to
01:28:11.840 consider when making implementation decisions for 24 years I served the people in the state of California
01:28:17.800 working in various Information Technology positions most recently is a head of Information Technology for small
01:28:23.520 State Department where I served as the Department's Chief Information officer information security officer lead programmer lead systems
01:28:31.040 administrator and network administrator and also the do helped us however I left Public Service last
01:28:38.400 month to join UB Cloud as a principal software engineer so UB Cloud we're building an open source alternative to
01:28:44.800 Amazon web services I now work with a great group of people and I get to write and review Ruby code all day and I'm
01:28:51.080 much much happier all right so I'm going to now Dive Right into a simple rooted example
01:28:56.679 just in case you're not familiar with it and this example it's a little bit more complex than hello world but it shows
01:29:02.560 Ro's key advantage over other R web Frameworks which is the ability to
01:29:07.600 handle requests during routing instead of separating the routing process from
01:29:12.840 the request handling process so with Rota all requests to the application are
01:29:18.360 yielded to the route block and the route block is responsible for handling all requests Now by convention R uses r as
01:29:26.159 the route block variable at any point in the route block you can do processing
01:29:31.600 related to the request for example if you want to check access by IP you could have that check at the top of the route
01:29:37.480 block and this would be equivalent to an application Level before hook in other
01:29:42.960 Frameworks now soon when we pass the access check we get to the first routing method so the r.on method is used to
01:29:50.119 handle branches in the routing Tree in this example the r start up on method is
01:29:55.159 passed two arguments called matchers now the first is the string employee which
01:30:00.880 will match if the next segment in the remaining path is employee and the second is the class
01:30:07.119 integer which will match if the next segment in the request path or the remaining path is an integer so if we
01:30:14.159 look at the combination of these two matchers they will match a request path such as SL employee 7 and since the
01:30:22.159 entire request path has been consumed by the two matchers the remaining path is
01:30:27.760 empty the matchers will also match a request path such as sl7 name and the remaining path after
01:30:35.560 this would be sln name which is what the routing methods inside the block will operate on it would not match a request
01:30:43.520 such as slender9 since the first segment is not employee and would also not match a path
01:30:49.920 such as SL employee slame since name is not an integer now if the request does not match the
01:30:56.880 Ron call r.on will return nil without yielding to the block and in this
01:31:02.600 example it would reach the end of the route block which results in a 404 response because the request has not
01:31:08.600 been handled now if the request does match the art on call it will yield to
01:31:13.840 the provided block and because the integer class matcher was used the block
01:31:18.880 will be yielded that segment of the request path converted to an integer so
01:31:24.239 for a get request such as employee 7 name the employee ID block variable will
01:31:30.679 be the integer set now inside the block first find is this is this code which shows the
01:31:36.920 primary advantage of RAB which is at any point during routing you can do processing related to the request now in
01:31:43.840 this case we're using that employee ID block variable to look up the employee by ID and then we're using that to set
01:31:50.159 the employee variable and all routes under this block can then access the employee now you can't get similar
01:31:57.000 behavior in other Frameworks using before hooks but this provides a simpler approach that avoids indirection if
01:32:03.719 you've ever had to debug issues involving the use of before hooks I think you can appreciate this
01:32:09.560 approach now what if there is no matching employee for the ID well in
01:32:14.600 that case you can use the next keyword to return nil From the Block which Roto will treat as a 404 response now that
01:32:22.679 ensures there is a valve employee for the rest of the block all right so the next routing method is r. is with a
01:32:29.639 string name match now r. is is similar to r.on except that it requires that the
01:32:36.600 request path has been fully consumed after all the matchers have been applied
01:32:42.239 now for our request since the employee in seven segments have already been consumed the remaining path is slash
01:32:48.119 name and the string name match will match that segment and since the entire
01:32:53.239 request pass has now been consumed by the matchers given to the routing methods the r. is Method will match and
01:32:59.880 it will yield to lock now inside the r is block the first method calls r. get
01:33:06.000 and this will match because the request being handled uses the get request method now the art get Block Returns the
01:33:13.199 string hello followed by the employees name as the block returns a string that
01:33:18.360 string will be used as the response body so let's see how a post request this
01:33:23.840 same path will be handled well the path of the request will still be fully consumed by the matchers given to the
01:33:30.280 r.on and r.is methods however the r. get method call will not match because this
01:33:35.960 is a post request and not a get request so R.G will return nil without yielding
01:33:41.880 to the block the next method call of the block is R about post which will match because this request is a post request
01:33:49.920 and so r. poost will yield to the block and in this case we will use the name parameter to update the employees name
01:33:56.960 and then we will redirect the request and since no arguments are given this will redirect to the same path but using
01:34:02.880 a get request and not a post request now hopefully this example was able to give
01:34:08.080 you a basic idea for how roa's routing tree works the most important part to remember is that Roa gives you the power
01:34:15.040 to do processing related to the request at any point during routing and this
01:34:20.360 reduces duplication and indirection and results in applications that are simpler and easier to understand Simplicity is
01:34:28.719 one of roa's four goals after 10 years developing Roa I still think that the primary benefit of Roa is it allows the
01:34:36.000 same application to be built more simply than in other Frameworks another of roa's goals is
01:34:43.199 performance now unlike the Simplicity goal which is subjective uh you can see objective differences between the
01:34:49.440 behavior or performance of Roa and other web Frameworks so we'll look at two benchmarks the first is r10k which is a synthetic
01:34:57.000 Benchmark that measures per request overhead and scalability for large numbers of routs Tink benchmarks
01:35:03.679 applications with 10 100 1,000 and 10,000 routes and to avoid web server
01:35:10.080 overhead it tests using the rack API directly so here are the request per second results for Roa rails Sinatra
01:35:17.760 Hanami and camping and it shows that R it is much faster than the Frameworks
01:35:22.880 unfortunately the scale of the graph makes it difficult to see how the other Frameworks compare so to make it easier
01:35:28.639 here's the same graph but using a logarithmic scale so this still shows R is much faster but it also shows that
01:35:34.520 Roa rails and Hanami all scale well for large numbers of routes it shows that
01:35:40.119 SRA and camping do not scale well for large numbers of routes and that's because both use a linear search of
01:35:46.080 routes during request handling artk also provides memory benchmarks and these show that Ro uses
01:35:52.400 less memory than other Frameworks ra uses about three to four times more memory than R in this
01:35:58.520 bench and I think the r 10K benchmarks are useful but they don't tell you much about real world performance
01:36:04.760 differences for that the teeken power web frame benchmarks do a better job so teeken power has been benchmarking web
01:36:10.880 Frameworks in many languages for over 10 years and Roa has led the Ruby web framework benchmarks ever since it was
01:36:17.679 added in 2017 now here are the composite score results for the most recent round of
01:36:23.760 tech and power benchmarks for Ruby web Frameworks and Roa leads in every category the weighted score for Roa is
01:36:29.920 almost double the weighted score for rails It lines up with results I've seen
01:36:35.119 from applications converted from rails to Roa where the converted Roa application is about twice as
01:36:41.119 fast now as the Benchmark show Roa achieves its performance goal it's the fastest R away forwork it scales well
01:36:47.760 and it uses the least memory it's the fastest framework mostly because it has the lowest per request overhead Ro is
01:36:55.760 designed to minimize the amount of work between when it receives the rack request environment and when it starts
01:37:01.600 processing the routing tree ver scales well because it uses a routing tree as soon as one branch of the routing tree
01:37:07.800 is taken other branches of the same level are no longer considered and finally what to uses the least amount of
01:37:14.159 memory because it is designed around a small core and that small core handles
01:37:19.239 basic routing and request handling all other features are added via plugins Rus
01:37:25.040 core is itself a plugin and plugins can override any part of Corea and any
01:37:30.480 previously loaded plugs as an example of its minimalism Rus core does not include
01:37:36.760 template rendering template rendering is supported via a plugin and it's common to use this plugin when you're
01:37:42.800 developing applications they targeting browsers however if you're designing an application that just serves API
01:37:49.080 responses via Jason you wouldn't need it in that case you'd want to use the Jon plugin which allows your route blocks to
01:37:56.080 return arrays or hashes and automatically converts those to Json and uses them as response
01:38:02.440 bodies the reason I refer to Roa as a toolkit is you can think of each plugin as a tool and different applications
01:38:09.280 require different tools and with Roa you only pay the overhead cost for the tools
01:38:15.440 that you choose to use Ro ships with over 120 plugins to handle the needs of
01:38:20.800 a wide variety of web applications and there are numerous external Ro plugins to handle additional needs so this
01:38:28.000 approach of having a small cord and shipping all the optional features as plugins is how R achieves its goal
01:38:34.760 extensibility 's final goal is reliability I think there are two aspects to
01:38:40.159 reliability the first aspect is internal reliability this is how the library itself is kept reliable and the second
01:38:47.280 aspect is external reliability which is how using Roa can lead to more reliable
01:38:52.719 applications so that's first discuss internal reliability where tries to ensure
01:38:58.360 internal reliability by having good test coverage in my opinion the minimum for
01:39:03.880 having good test coverage in rudby is 100% coverage I saying 100% coverage
01:39:10.800 means nothing but less than 100% coverage means something at least means
01:39:16.920 you have code that is not being automatically tested and in my experience untested code is the most
01:39:23.360 most likely place that you will find bugs not that 100% coverage does not ensure robust code you can have 100%
01:39:30.239 coverage and still have bugs you can be executing code and not checking for proper results you could be using unit
01:39:37.239 tests and no integration tests and not testing that the entire system works together fora and other open source
01:39:44.239 libraries I maintained I consider 100% coverage as the starting point not the Finish Line I no longer release a ruby
01:39:50.920 Library without 100% coverage now when I started out developing Roa targeting 100% coverage meant 100% line
01:39:58.440 coverage and after Ruby started supporting Branch coverage and simple C was updated to support Branch coverage I
01:40:04.440 expanded that to also include 100% Branch coverage so coverage in rate is tested before every release and if for
01:40:11.360 some reason it is less than 100% appropriate steps are taking to get it back to 100% now coverage isn't the only
01:40:17.800 approach that Ro uses to Ure internal reliability another approach that Ro uses to ensure entire relability is that
01:40:24.440 it uses almost no mocking in its tests mocking in tests often leads to tests that pass but have issues in production
01:40:31.520 and avoiding them leads to more reliable tests uh talk about cohesion um or
01:40:37.960 coupling mocking leads to very tight cop light in your tests it's one of the
01:40:43.000 reasons it's bad the Final Approach that Ro uses to increase your internal relability is it deliberately limits the
01:40:50.040 libraries pens on corers only run dependency is wrapped um some plugs
01:40:55.880 depend on additional libraries but in general dependencies are deliberately kept to a minimum to limit
01:41:02.639 risk so now that I've discussed how R achieves internal reliability let me discuss how R achieves external
01:41:08.159 reliability now Ro combines two development approaches uh to achieve external reliability and the First
01:41:14.159 Development approach is immutability R applications are designed to be frozen in production and when testing and this
01:41:21.480 reduces the possibility for thread safy issues as well as memory leagues to the unexpected object retention now
01:41:28.000 immutability is not just for reliability in Ro either when Roa immutability also
01:41:33.880 improves performance when you freeze your Roa application Roa knows there'll be no further configuration changes to
01:41:40.920 it R then determines whether the methods that it has that are designed for extensibility have not been overridden
01:41:48.159 and in that case it overrides the default extensible methods with optimized methods and that gives you the
01:41:54.080 best of both worlds extensibility when you need it and maximum performance when you
01:41:59.760 don't second development approach related to liability I refer to as Pollution Control more explicitly Nam
01:42:06.040 space pollution control or limits pollution of your constant method and instance variable name spaces in your
01:42:13.840 application all internal constants in the Roo class start with Roa to avoid conflicting with user Define constants
01:42:21.239 Ro limits instance variable pollution by prefixing all internal instance variables in route block scope with an
01:42:27.760 underscore if you've ever developed a snch application and try to use request or response instance variables you will
01:42:34.400 appreciate this ask me how I know word limits method Solution by only
01:42:40.440 defining six methods in Ro block scope beyond the methods that are defined in object and some pivate methods that
01:42:46.239 begin with an unders and that makes it less likely that a user defined method will conflict with a ro method so now
01:42:52.800 that giving a brief Taste of Roa and discuss how Roa has achieved its goals I start discussing the first 10 years of
01:42:59.239 Roa so roa's first release was on July 30th 2014 and its most recent release
01:43:04.639 the 125th release was last week now I don't like waiting long to use new
01:43:10.040 features so Ro to fall is a simple to understand release schedule there's a new Ro to release every month around the
01:43:16.239 middle of the month ever since 2014 I also don't like it when changes
01:43:21.639 to a library break my applic so rot places a high priority on backwards
01:43:27.000 compatibility I think the compatibility is so good that the majority of applications that worked with the first
01:43:32.320 release Roa 0.9 would still work if you upgraded them to the latest release Roa
01:43:37.920 3.86 with one main exception if we go back to our first example we see that it
01:43:43.800 uses the integer class match however what did not support using the integer class as a match until R to
01:43:50.639 2.27 before R to 2.27 this type of matcher would generally be written using
01:43:56.360 what is referred to as a placeholder string with placeholders in the string being prefixed by a colon however this F
01:44:03.080 resulted in two issues first it resulted in redundancy most developers have a placeholders
01:44:10.119 similar to The Block variables it's not technically a problem but it is a tad in the way the actual problem was a
01:44:16.560 performance problem which is that you needed to scan all the strings that are used as matchers to see if the string
01:44:23.080 contains a placeholder and then treat the string differently if it has a placeholder and strings are the most common type of matcher so this check
01:44:29.679 resulted in a measurable slowdown even if you were not using placeholders now three removed support
01:44:36.360 for placeholders and string matchers by default and in order to support backwards compatibility or to freeship
01:44:42.080 with a placeholder string mattress plugin I analyzed a couple of my open source applications checking out the
01:44:48.239 commit where the application was converted from Sinatra or rails to R 0.9
01:44:53.560 and trying it with the current version of Roa and in both cases adding this placeholder string mattress plugin was
01:44:59.960 the only Rota related change necessary to get specs passing with the current version of Roa comparatively Roa did
01:45:06.960 even better than SQL since there were generally three to four lines needed to be changed for the tenure application to
01:45:13.000 work with the current version of s I mentioned that one of the reasons for breaking backwards compatibility was
01:45:19.040 to improve performance so how much of this change and other changes improve Ro's performance over the last 10 years
01:45:27.239 well to determine that we're going to look at some more r10k Benchmark results to see how roa's performance has
01:45:32.400 improved over time additionally Roa is a fork of another framework named Cuba so
01:45:37.679 we're going to compare Roa to CU so we're going to start with r's initial release compared against the current
01:45:43.880 Cuba release at time as you can see performance is basically the same for the initial release I was focused on
01:45:50.560 differences in rout block handling handling block responses and getting the plug-in system working I wasn't focused
01:45:56.800 on performance since CUO was already much faster than other Ruby web Frameworks at time less than a month
01:46:03.199 after the initial release I released R 1.0 and that has a massive boost in performance over the initial release
01:46:09.440 with a number of additional optimizations at the time most of the matchers in Roa were based on regular
01:46:15.760 expression scanning and the most important optimization was the caching of regular Expressions instead of
01:46:21.760 generating a new regular expression object for every natural about 6 months after releasing R to 1.0 I released R to
01:46:28.960 2.0 which improved performance over 1.0 by about 20% this performance
01:46:34.639 Improvement was due to reducing allocations and operations during matching so that each match attempt did
01:46:40.719 not modify the request environment about two and a half years after that I released R of 3.0 which
01:46:46.880 improved performance over 2.0 by about 40% and this performance Improvement was
01:46:52.159 mostly due to avoiding regular Expressions during matching and the remove placeholders during string
01:46:57.800 matching instead of regular Expressions string Methods such as start with and index are used and this idea was taken
01:47:04.840 from syyro a routing Library by the same author as cubba by January 2021 with the release
01:47:11.560 of Rota 3.40 performance have increased another 15% now this performance
01:47:16.639 increase was due to a couple of optimizations during this time period is when I added the optimization during
01:47:22.199 application for ing Additionally the performance of string and segment matching was improved by about 15% and
01:47:28.480 terminal matching by about 400% between 3.40 and 3.60 performance
01:47:34.440 increased another 30% now this was due to additional optimizations on the most common matchs Ro's current performance
01:47:41.239 is about the same as Roa 3.6 which Ro's initial release on the current release performance in this
01:47:47.520 Benchmark improved by a factor of 12 I think that's pretty amazing considering
01:47:53.080 that even at roa's initial release it was one of the fastest Frameworks however this is not the limit
01:47:58.560 of roa's performance using the optimized string matchers optimized segment matchers and plane hash response headers
01:48:05.199 rotor plugins performance can be improved in additional 35% this does require some small
01:48:11.159 sacrifices and usability though all right so RK is a routing and proquest overhead Benchmark and Roa has
01:48:17.920 improved greatly over the years of those that's not the only way that Roa has improved performance many of the plugins
01:48:23.800 that ship with Roa have been optimized as well for example the render plugin has shipped with every release of Roa
01:48:30.159 but it and other related plugins were extensively optimized a few years ago for simple templates the render plugin
01:48:36.360 is about four times faster than it was originally speaking of plugins R to 0.9
01:48:43.119 Shi with 15 plugins and R to 3.86 shifts with over 120 plugins more than eight
01:48:48.920 times as many as the initial release so I'm going to take you in a quick to for the last 10 years of R of
01:48:55.800 plugins now in the initial release in addition to rendering Ro ship of plugins for handling exceptions customizing
01:49:02.920 default heads and 404 responses handling flash messages streaming responses and
01:49:09.159 operating as rack middleware one of the most important plugins was the ability to use separate routing blocks if you
01:49:16.159 remember back to our initial example I mentioned that all requests are yielded to the route block and the route block
01:49:22.159 determines the response now in Ruby you cannot split a block across multiple
01:49:27.280 files and having all routes in a single file only makes sense for small applications to handle large
01:49:33.400 applications you need a way to separate the route inlock and even the very first release report supported that via the
01:49:39.280 multiroute plugin so with the multiroute plugin you call r. multiroute in your main routing block and it would dispatch
01:49:45.960 the separate routing blocks based on the next segment in the remaining path and those writing blocks would generally be
01:49:52.159 stored in separate files based on the route segment name like this and that made it simple to organize large
01:49:57.920 applications in Roa and allowed even the first release of Roa to scale from simple single file applications to
01:50:04.000 decent size applications R 1.0 added 11 new plugins not in the initial release and these
01:50:09.960 included plugins for returning arrays and hashes is Json cross-site request forgery protection brand new collection
01:50:17.119 of partials in one call and having a separate view subd directory for separate branches of the routing tree
01:50:23.119 Additionally the render plugin was expanded to support the automatic escaping of output and templates greatly
01:50:29.040 reducing the likelihood for cross-site scripting issues I think my favorite uh plugin
01:50:35.400 edition 1.0 is called symbol views the symbol views plugin is very simple but it allows you to replace manual calls to
01:50:42.239 view to render templates and just have the route block Patronus symbol and the small change dries up a lot of Route
01:50:48.360 code makes the common case of rendering a template inside a layout even simp it is in Sinatra essentially rails now not
01:50:56.960 everyone is a fan of this T style but just because I think a particular style is nicer doesn't mean I think I should
01:51:02.079 force it on all Ro users between R 1.1 and 1.3 25 more
01:51:08.119 plugins were added including plugins for managing HTTP caching incrementally
01:51:13.159 rendering templates compiling compressing and serving asset files for 1.2 added the mailer plugin which
01:51:19.880 brought the benefit of routing trees to sending email from applications so here's an example that uses the mailer
01:51:26.040 plugin generally use the mailer plugin in a r subass designed specifically for sending emails unlike Road web
01:51:33.159 application which is designed to handle HTTP requests a road mail application is designed to handle internal requests
01:51:40.199 however sending mail with a mailer plugin is done by providing a path just like with an HTTP request or a mail
01:51:46.920 application uses the same basic routing methods that a r web application uses and just like in a web application at
01:51:53.920 any point when handling a mail request the Lord mail application can do processing related to building the email
01:52:00.360 so here we're setting the sender and recipient addresses so those don't need to be duplicated inside every mail
01:52:06.079 handle block the r. mail method is used to handle mail routes it operates
01:52:11.280 similarly to R.G get and r. poost in this case the time off matcher matches
01:52:16.800 the remaining path the method will yield it to the block and the block sets the subject for the mail and Returns the
01:52:23.560 symbol for the maale templat render referning the symbol works because this mail plugin also uses the symbol of use
01:52:30.480 plugin between order 2.0 and 2.29 22 more plugins were added and these
01:52:35.880 included support for setting preload headers for assets serving public files
01:52:40.960 at a specific place in the routing TR rewriting paths prior to routing parsing
01:52:46.560 Json request bodies to parameters fast o1 routing to static paths and having
01:52:52.079 the routing support file extensions in the request path especially we 2.27
01:52:58.159 added a class mattress plugin which allows you to specify the handling of arbitrary classes that are used as
01:53:04.920 matchers going back to our initial example we see that we are using the integer matcher which yields an integer
01:53:11.400 and we then looking up the employee using that integer I have to manually handle the case where that look
01:53:17.320 fails so using the class mattress plugin we can simplify this we can register the
01:53:22.480 employee class as matcher and build on top of the integer matcher there's match by the integer matcher the value is
01:53:29.119 yielded to the block as an integer and the block can then do the employee lookup and that allows the rotting tree
01:53:34.920 to be simpler every case you're trying to match an employee you can pass the employee class as a match and it will
01:53:41.440 yield the employee object to the routing block if the segment was for a valid employee if the segment was not for
01:53:48.119 valed employee it just wouldn't match the fre .0 and 3.29 12 more
01:53:54.560 plugins were added including support for encrypted sessions early hints content
01:54:00.079 security policies processing incoming emails using a routing tree logging in
01:54:05.239 common log format showing nice exception handling pages in development splitting the riding tree into sub trees without
01:54:11.880 using regular expressions and supporting stronger cross-site request forgery protection using tokens specific to the
01:54:18.840 request method and path we a 3.3 editing typ cast Fram plugin for handling the
01:54:24.599 typ casting of submitted parameters to expected types so here's an example of use showing the automatic conversion of
01:54:30.880 a given parameter to a to a positive integer ensuring that attackers can not try to submit an array or hash P cast
01:54:37.960 pram say support foress parameters typ casting arrays of values to expected types and custom parameter types it's
01:54:44.440 designed to be simple and not for both which you heard at 3.30 and 3.59 17
01:54:50.639 more plugging were added and these includ support for host authorization trying multiple render engines and
01:54:56.760 multiple view directories when rendering templates using arbitrary objects as matchers during routing supporting
01:55:03.480 multiple directories for public file cming at different places in the routing tree and a simpler approach to dispatch
01:55:09.040 into separate routing trees which can automatically set the view sub directory during the dispatch which in r 3.60 in the current
01:55:16.400 version 3.86 19 more plugins are added and these plugins included support for
01:55:21.800 handling arbitary objects returned from Route blocks autoloading hash branches and development for faster development
01:55:28.560 and testing setting permissions policy enforcing cookie Flags handling invalid
01:55:34.400 request bodies and measuring line and Branch coverage of templates even in Ruby versions that do not support
01:55:41.079 coverage for evalid code order 3.79 added an hmac paths
01:55:47.079 plugin which allows you to easily prevent path enumeration by including an hmac in the path
01:55:53.400 going back to our initial example we see that this allows anyone to issue requests for this Branch so what if you
01:55:59.679 want to prevent someone with access to the application from enumerating your employees using the hmac paths plugin
01:56:06.639 you could wrap that routing clock in r. hmac path and when generating paths in your application you would call the hmac
01:56:13.599 path method with the path and it would prefix an hmac and some metadata such that r. hmac path will consider it valid
01:56:21.239 so the hmac path was expanded in R 3.80 to support session specific hmax so the
01:56:27.239 paths valid for One login user would not be valid for different loged in user and it was expanded again in order 3.81 to
01:56:34.480 support paths that are only valid for a limited time so it's a brief tour of plugins that Ro has added in its first
01:56:41.360 10 years I want to finish up this presentation by briefly discussing three open source applications that are built
01:56:47.079 on top of Ro and how they are using Ro features so the first application is CFA web which is a web front end for crafa a
01:56:54.639 ruby Jam for working with CFA a distributed published scribe Cube now
01:56:59.840 craf web ships with all of its asset files inside the gem it uses Ro's public
01:57:04.880 plugin and it serves the assets using a path based on the gem version and this
01:57:10.480 automatically handles cash and validation by using A New Path for each gem version craft web uses the custom
01:57:17.639 block results plugin so that route blocks can return craft web specific objects which are translated into HTTP
01:57:23.960 responses and this reduces duplication inside the rout blocks second
01:57:29.079 application is UB Cloud which is the main application I work on so I mentioned earlier UB cloud is an open
01:57:34.239 source alternative to Amazon web services UB Cloud uses the rodo authentication framework to handle
01:57:39.920 authentication rodof is Ruby's most advanced authentication framework with built-in support for multiactor
01:57:45.639 authentication such as top and webo M now rodo is a r plugin but you can use
01:57:51.239 rodo even in non-r applications by using roa's middleware plugin and using the Roa application as
01:57:58.000 middleware ubad uses multiple roof configurations as it uses rof to handle authentication both for browser logins
01:58:04.920 as well as for it Json API now this is the section of UB Cloud's main route block that's designed
01:58:10.760 to handle browser requests and GitHub web hooks UB cloud is a decent Siz application so it uses the hash branches
01:58:17.840 plugin to separate the routing trees it actually has two separate dispatches to routing trees here here this one is for
01:58:23.400 the main application and it's used for login users in browsers web hooks dispatched to a different set of riding
01:58:29.679 trees because they don't need cross-site request forgery checks nor do they require the same authentication as login
01:58:36.000 users this type of possible setup as possible in other Frameworks I think it's significantly simpler in
01:58:42.520 Roa so the third application is Bridgetown which started out as a static site generator you can now do both
01:58:48.520 static site generation as well as being a full stat framework Bridgetown uses rotated to handle
01:58:54.280 routing so here's the routing tree for Bridgetown server it loads the Bridgetown server plugin and all rep the
01:59:00.400 application use the Bridgetown writing method so what does the Bridgetown server plugin do one thing it does is it
01:59:06.040 loads a bunch of other plugins most of these are plugins that ship with Roda um a few of these are plugins specific to
01:59:12.719 Bridgetown uh for example the SSG plugin is a Bridgetown specific plugin for serving the statically generated files
01:59:19.880 uh it's based on Ro's public plugin but it autom tries multiple file paths in order to allow for nicer
01:59:26.920 URLs that brings us to the artop Bridgetown method that method is defined by the Bridgetown server plugin uh this
01:59:34.480 method is running request scope so it first initializes some Bridgetown specific code in route lock scope it's
01:59:40.800 configured with a base path it tries to remove the base path from the requests and then it tries serving statically
01:59:47.040 generated files if there is no statically generated file related to the request then it goes through all of the
01:59:53.760 dynamic routes using R is routing methods now this had a bit more dcy than I'd like uh so a couple days ago I sent
02:00:00.800 them a pull request to change it uh to this which has equivalent Behavior and the pull request was quickly accepted I
02:00:07.639 think this change shows a good job uh of showing the power of Roto because you can write run any code that you want at
02:00:14.639 any point during routing you can use any Ruby code you're familiar with to dry up your routing code so that's how some
02:00:21.320 production opens Source applications are using Roda to simplify their web development as we get to the end of this
02:00:27.040 presentation I'm happy to announce that after 10 years Roa recently passed 10 million downloads so you haven't already
02:00:33.679 started using Roa now is a great time to start a good fun learning about first 10
02:00:38.760 years of Roa that concludes my
02:00:48.760 presentation we have time for questions
02:00:56.320 yeah uh so obviously web Frameworks web toolkits are right in the middle of the
02:01:01.840 attack surface for you know all the different kind of things that bad people are trying to do on the internet uh you
02:01:07.320 mentioned a bunch of features for like adding you know cookie cookie encryption and hmax and like offensive things that
02:01:13.159 you're doing to to reduce that but presumably you also get like people saying hey I found a bug and road as security applications how do you think
02:01:19.040 about that as it maintaining um yeah I certainly security bugs are going to be the most uh important bugs to fix um I
02:01:26.840 say I think Roa has had one or two security issues uh in the time I've been
02:01:32.960 maintaining it um might have to look through the change L and see it's certainly been a number of years since
02:01:38.000 some was reported a security issue in Roa um so uh yeah certainly if if one
02:01:45.520 comes in that's treated with the highest priority sure does that kind of shortcut the monthly release process or try to
02:01:51.199 keep yeah certainly so in general because Ro is released every month I don't generally do Point releases uh
02:01:57.920 there's only two reasons to do a point release one is security issues the other is fixing regressions from the previous
02:02:03.440 release so if reg if there's a regression from the previous release that will get a bug fix of like point
02:02:08.920 one release um if it's a regression for more than one release ago then it usually waits the next release makes
02:02:15.280 sense thank you
02:02:25.440 hi uh thank you for the talk first of all it's getting dangerously close to my bedtime so forgive me if this is a
02:02:30.840 terrible question but one thing I wanted to understand better it's it's very clear given the the way uh think about
02:02:38.159 the routing being hierarchical and processing happening as part of that is there any built-in caching that happens
02:02:43.920 for let's say when part of a route is handle so in the example you pull up the employee is that cached for all other
02:02:51.079 routes that Spa off of that or is that me go back to the initial example so you
02:02:56.679 can go through this so one of the things that makes Roa Cuba syyro different than
02:03:03.560 other uh Frameworks is that this is really what you could call instance based routing every there's no caching
02:03:11.040 at all every request comes into the route block uh there's not really any caching that's going on here everything
02:03:17.920 just goes through the reason it's fast is because it's very low overhead not because there's any fancy caching going
02:03:24.159 on uh I wouldn't say there's none because like the render pluging does extensive caching to speed things up um
02:03:30.480 but for the general routing part uh there's not much caching that goes on if you use regular Expressions those are
02:03:37.000 like sort of converted in cach and back when everything was regular expression based the caching was very important but
02:03:42.360 now that pretty much everything just uses string Methods um what's say everything like I think the integer class matcher uses regular Expressions
02:03:49.280 internally that are cached that's that's one thing we're cashing is important um but for General things like the employee
02:03:55.159 and name part uh those just use string Methods so there's no there's no really caching need for it it's just fast
02:04:01.280 because string method
02:04:06.760 fast I'm glad we on the slide because I have a question about this next andless okay um I was actually looking this go
02:04:13.040 the other day trying to figure out what's going on there is that inside of a loop and I noticed in another slide
02:04:18.280 for mail it was like a bang method I assume that raised is an exception and I think another plausible way of dealing
02:04:23.960 this is just like a return unless so I'm really curious like why the next why not
02:04:29.719 a return or raising the exception so return would theoretically work in this case but only because the route block is
02:04:36.040 technically uh used to define a method for performance reasons it was originally done that way originally it
02:04:42.719 was just an instance of Al Block in which case return wouldn't work because you can't return out of a regular block
02:04:48.239 um it was changed to defining a method uh this was back with Ruby uh instance
02:04:53.800 Dev basically old versions of Ruby if you instance Deval block it would create a Singleton class which is a very slow
02:05:00.280 thing to do so one of the things that did to work around that is it took most of the blocks like the route block and
02:05:06.639 Define them as methods which you don't need to Def find a singal in class where you can just call so that was a
02:05:12.000 performance thing so return would theoretically work here um but only because
02:05:17.920 uh because of the way that the route block defines a method what next does here next in any block
02:05:24.199 doesn't have to be a loop next in any block sort of jumps to the end of the Block in this case because no argument
02:05:29.840 is given to next it's really like next nil so basically this is a quick way to return nil From the Block so the way
02:05:36.360 rotor routing works is every time you get into a block sort of that block takes over so like if you don't do
02:05:43.520 anything to the block it comes to the end and that's when it does you know will turn to 404 response but like let's
02:05:49.719 say it goes down here it yields to this block block yields this block yields to this block and this returns now it doesn't go past this once this block
02:05:57.079 returns once you take the final inside writing method and the block returns it throws the the response so it jumps all
02:06:03.800 the way through you don't need to worry about return things uh technically this is how s works as well so when you have
02:06:08.920 a snra block it ends up throwing uh and there's a basically a catch thing at at the end surrounding the request that's
02:06:15.440 why things like you can you don't need to worry about like double RS or double renders um in Roa because let's say you
02:06:22.040 have you know r. redirect if something you can have code after that because if the redirect happens that throws so you
02:06:28.800 can never have someone redirect and do something else because the redirect ends the processing at that point and throws the response directly to the
02:06:35.840 user was there any like performance issues with throwing no throw throw throwing in in Ruby is actually very
02:06:42.440 fast um it works similarly to how exceptions work and you think of
02:06:47.800 exceptions as slow but the slow part of exceptions is not the throwing part the slow part of exceptions is building the
02:06:53.000 back TRS that's what makes R exceptions slow the actual catching and throwing of
02:06:58.159 stuff is actually very fast um I do have another question about
02:07:05.159 pattern matching okay um I worked with a lot of case in and I'm curious like um
02:07:10.760 are you using pattern matching in case in here potentially even with RVs um or
02:07:16.199 is that just like it seems like it be a different thing than Ro I'm curious if you're thinking about that like have you build an o that's using Ruby pattern
02:07:22.719 matching yeah I I have not done anything with pattern matching um pattern matching uh in Ruby is cool but it's
02:07:28.800 also not very fast um other thing is people ask why I do this but Roa
02:07:34.360 actually still reports Ruby 1 n all the way to Ruby 34 so it it has a incredibly wide range of versions at sports but the
02:07:42.159 the main reason it's not used it's just not very fast uh and we don't really need to use it um there's always ways
02:07:50.599 you can do things without pattern matching they make some code nicer um but there's a lot of cases where it's
02:07:56.800 I'd say overused nice right I'll pass that over
02:08:05.760 there quick question with the possible long answer what was the original motivation for Roa given it's only 10
02:08:11.760 years old thank you thank you for the question so the original uh original ID here is I was a rails programmer for a
02:08:17.599 few years from like 2005 to about 200 eight and then snatra came out I love
02:08:23.719 snatra I was snatra programmer for a long time but I got to the point where snatra because every route is separate
02:08:29.360 you end up a lot of duplication in your routes that's in 2014 I discovered Cuba
02:08:34.599 and Cuba was this hierarchical approach where you could reduce duplication in all of your routes so I originally
02:08:40.880 contacted the Cuba guys and I'm like hey I really like this but I don't think it's as you know nice to use asra and
02:08:46.520 they're like well it is what it is we're not going to change it which is fine that's when I forked it and
02:08:52.040 the original name for Roo was SBA half Sinatra half CU so I I Chang it to Roo Ro the name
02:08:59.320 Roa comes from a video game where Roa is this big alln tree so that's why the C
02:09:06.520 didn't even call the routing tree riding tree is something that I I came up with that's why it's called Roa that's the
02:09:12.000 original thing it's like combine the best aspects of Sinatra with the hierarchical riding tree from Cuba sort
02:09:18.320 of how it is
02:09:29.280 um how does like wet or anything of like with the Justus in time compiling stuff that's come on in Ruby recently does
02:09:35.199 that affect the performance or or any of the Benchmark comparisons that you were show yeah so when I benchmarked with wet
02:09:41.239 wet does a good job I think for the 10 and 100 Route thing it it makes it significantly faster I think when you
02:09:47.360 get to the 100 the 1,000 and 10,000 routes so actually makes it slow because the blocks get so humongously
02:09:54.000 gigantic that that W does not do a good job optimizing at that point but for reasonable stuff W will definitely speed
02:10:00.280 up your road app um it provides a bigger speed up to rails apps because rails
02:10:05.920 apps are less efficient F thank you for your effort
02:10:12.639 here and I was a question about the all the world
02:10:18.599 maintaining so back from 1.9 uh I mean it's it's
02:10:28.199 huge why bother supporting I get that
02:10:33.320 question I get that question quite often um so my my D here is a it's not that
02:10:39.440 difficult to support I'd say it's kind of annoying because there's newer things in Ruby um things that could improve
02:10:44.840 performance slightly um a lot of just nicer things like it'd be cool to use uh
02:10:50.119 23s lonely operator to simplify code um but the main reason I do it is let's say
02:10:56.239 you have an old rails app or an old application you want to upgrade um you can convert assuming it's running
02:11:02.920 ruby9 early versions of were actually supported ruby8 even back 2014 that was
02:11:08.320 considered kind of ridiculous um but you can if as long as it's done to One n you can actually go convert it to Roa and
02:11:15.199 then jump directly from 1 n to 33 and when I mean obviously if there's other things it's using they probably won't do
02:11:21.760 a big job but root it and SQL actually pretty much most of my libraries will go sport all the way back to One n so you
02:11:28.239 could convert and then upgrad in one go um from Ruby one9 all the way to
02:11:38.920 33 who's uh with me and want in so much to try thr
02:11:47.000 now yeah so this is incredible thank you thank you very much
02:11:59.040 right U I'm gonna ask um academia's Team come
02:12:05.079 over Janie come over come over and yeah let's just one
02:12:12.880 um say thank you to the team who put this all
02:12:18.119 together and yeah please you
02:12:28.199 knowla thank you for having um the Ruby Meetup event here in Academia and I
02:12:34.320 really want to thank Rob and atio who are part of the recruiting team um for helping uh set up the event as well as
02:12:41.599 our facilities manager Michael who's all the way back there as well as Minnie and
02:12:46.960 few other folks who uh are colleagues within the crowd here right now
02:12:52.040 um huge thank you for everyone attending um if you're interested in talking a
02:12:57.079 little bit more about what we do here at Academia please uh see us afterwards and we can tell you a little bit more about
02:13:02.559 what our platform does thank
02:13:09.040 you don't forget on the back of those cards there's a QR code and it leads to
02:13:15.000 the job openings at Academia who
02:13:22.360 all right thank you thank you guys um so with that this is uh we're finalizing our program don't forget to sign up for
02:13:29.800 at Luma SF Ruby for our next events and uh I'm um we can um stay here for you
02:13:39.520 can have uh this till n um and yeah if
02:13:44.559 you want we can later grab a drink somewhere un officially yeah uh but yeah so that's
02:13:51.800 that's thanks so much for coming again uh see you next time thank you
Explore all talks recorded at SF Bay Area Ruby Meetup
+24