Summarized using AI

Frontend Ruby with Glimmer DSL for Web

Andy Maleh • March 06, 2024 • Montréal, Canada • Talk

The video titled 'Frontend Ruby with Glimmer DSL for Web' features a presentation by Andy Maleh at the Montreal.rb Meetup, discussing the innovative framework Glimmer DSL for Web, which allows Ruby to be used for Frontend development, as opposed to JavaScript.

Key Points Discussed:
- Introduction to Frontend Technology: The presentation begins with audience participation to understand their current frontend technologies, with members using various JavaScript frameworks as well as jQuery.
- Glimmer DSL Introduction: Maleh introduces Glimmer DSL for Web as a continuation of his previous talk 'Intro to Ruby in the Browser,' discussing its goal to revolutionize frontend development by enabling developers to use Ruby.
- Benefits of Ruby in Frontend Development: Maleh outlines several advantages of using Ruby, including:
- Improved productivity and maintainability due to Ruby's concise syntax compared to JavaScript.
- Readability of Ruby code enhances developer experience and reduces time for bug fixes and feature additions.
- Isomorphic applications can use the same programming language (Ruby) on both frontend and backend, minimizing friction and maximining efficiency.
- Ruby in the Browser: Insights into running Ruby in the browser through WebAssembly (Wasm) and discussions on Opal Ruby, a Ruby to JavaScript transpiler, are provided. Maleh explains that full Ruby can run in the browser, potentially replacing JavaScript in the future.
- Glimmer DSL Features: Examples of implementing user interfaces with the Glimmer DSL are showcased, emphasizing:
- The simplicity and intuitiveness of building complex components with far less code.
- Demonstrations of data binding and separation of concerns using Model-View-Presenter (MVP) architecture.
- The use of declarative syntax, making the code cleaner and readable.
- Examples of Code Transformations: Maleh compares an original React component codebase (523 lines) with its refactored version in Glimmer DSL for Web (40 lines), showcasing a significant reduction in code size and complexity, while maintaining clarity.
- Future Improvements and Features: The presenter concludes with discussions on planned enhancements for Glimmer DSL, such as adding support for web components, integrating frontend routing, and future support for Ruby Wasm.

In conclusion, the presentation highlights Glimmer DSL for Web as a powerful alternative for frontend developers who prefer Ruby, promising improved productivity and code maintainability. Maleh emphasizes the evolution towards a Ruby-centric development approach for the web, effectively challenging the dominance of JavaScript frameworks.

Frontend Ruby with Glimmer DSL for Web
Andy Maleh • March 06, 2024 • Montréal, Canada • Talk

Montreal.rb Ruby Talk 2024/03 - Frontend Ruby with Glimmer DSL for Web - Andy Maleh - Senior Software Engineer at Lexop

GitHub: https://github.com/AndyObtiva/glimmer-dsl-web

Rubyists would rather leverage the productivity, readability, and maintainability benefits of Ruby in Frontend Web Development than JavaScript to cut down development cost and time by half compared to using popular yet inferior JavaScript frameworks with bloated JavaScript code as per Matz's suggestion in his RubyConf 2022 keynote speech to replace JavaScript with Ruby. Fortunately, this is possible in 2024!

This talk is a continuation of the previous Montreal.rb talk "Intro to Ruby in the Browser", which ended by promising a new way in the future for developing Web Frontends that would completely revolutionize the way we think about and do Frontend Development using Ruby instead of JavaScript. The future is now!!! The simplest, most intuitive, most straight-forward, and most productive Frontend Framework in existence is here! It is an open-source Ruby gem called Glimmer DSL for Web.

Think of Glimmer DSL for Web as the Rails of Frontend Frameworks. With it, you can finally live in Rubyland in both the Frontend and Backend on the Web! That opens up the door to ideas like rendering Frontend Components in the Backend as Server Components in the future, eliminating the conflict between ERB and JS frontend rendering technologies by leveraging highly readable, maintainable, and productive Ruby code isomorphically.

Montreal.rb Meetup March 2024

00:00:01.160 okay so before we start I want to just uh uh ask the audience what kind of front-end technology are you using like
00:00:08.120 are you using a JS framework are you using jQuery are you using vanilla JavaScript so how about we go through
00:00:13.639 start with you Nicholas first uh currently I'm using well there's leg SK
00:00:20.680 with cuff script and jary and I'm moving onwire with the stimulus and JavaScript
00:00:27.279 nice you're using C coffee script and J query and with a bit of hot wire yeah got it I'm moving on my personal project
00:00:34.280 I'm removing into the flex ecosystem mhm got it by the way if if you're not
00:00:39.960 employed you can skip but uh if you want to talk yeah you can Skip it's okay go
00:00:45.480 ahead I'm using a VJs vuejs okay what about the last project that I worked
00:00:50.719 with was a turbo links okay turbo link UJS
00:00:58.920 UJS react JavaScript jQuery and AST
00:01:04.720 react JavaScript jQuery and what Astro Astro yeah okay yeah yeah so it's an
00:01:11.479 interesting variety some people are still using traditional Technologies like jQuery or even coffee script but
00:01:16.759 there there are a few and there is a number of people that are using VJs and one person's using react uh so yeah did
00:01:24.400 you want to say uh something Thomas I would say J C and then scpt is more Legacy technology
00:01:32.320 right right jQuery is still actively developed and still maintained so I wouldn't consider that Legacy but coffee
00:01:38.119 script is certainly Legacy so uh the topic today is front end Ruby with glimmer DSL for web uh I'm a senior
00:01:45.880 software engineer at leop I've been here for about two years and I have 20 years of software engineering experience uh
00:01:52.640 using Ruby uh rails uh Java and uh Visual
00:01:58.840 Basic but the first of all the Ruby is available on the was so the web assly so
00:02:07.680 the the whole Ruby compile uh Ruby virion machine can be compiled into the
00:02:13.239 the web assembly so that you can run the full full Ruby uh any restriction uh in
00:02:22.840 in the browser so that uh that is that is quite wonderful but uh
00:02:30.599 when I got this proposal from the community I I just thought it was it
00:02:38.040 could be a yet another platform of the that's Ruby supports uh for example Ruby
00:02:46.080 is run in Linux and a FreeBSD and windows Mac OS and a and and a a from
00:02:54.480 IBM and many platforms then we I start
00:02:59.599 we we got yet another platforms but uh uh the was is more than that because the
00:03:07.400 wi r f willu be in in browser so that uh maybe we
00:03:15.400 can replace the you know replace the
00:03:22.000 JavaScript by total Ruby not the you know by not by emulation not by the you
00:03:29.080 know the hiding something a fully uh
00:03:34.599 implemented Ruby in the browser that is kind of you know game
00:03:40.360 changing yeah Ru now the endan which is
00:03:46.599 who is in charge of the you know many things like a pro Ty Prof and you know
00:03:52.879 the many games and uh the after carot and and then he also played with the
00:03:59.680 Ruby wasn't and then he made some kind of the you know uh interactive Ruby
00:04:06.200 environment in browser so that all ruby program will be run on the browser so
00:04:14.239 that you don't have to worry about the you know the soundboxing and then you know the uh the protecting execution in
00:04:23.400 the in the server site or something like that okay so that was Matt the creator
00:04:29.880 of Ruby uh giving a keynote speech at Ruby comp 2022 which I've presented out
00:04:35.840 as well uh and he was telling us that with Ruby WM you can actually run a
00:04:42.759 fully compiled Ruby in the browser using wasm technology and that means we can start to explore replacing JavaScript
00:04:49.800 which is what he said uh with Ruby um which is great um but however there is
00:04:55.880 another option which is uh opal Ruby opal Ruby is a ruby to JavaScript transpiler which I've actually covered
00:05:02.800 in a previous talk at Montreal RB 6 months ago titled intro to Ruby in the browser and it lets you do the same
00:05:09.919 thing but which with much smaller
00:05:29.520 velers can write Ruby code in both the back end and the front end so why why Ruby in the browser uh so
00:05:37.160 I'm going to go over things that I actually did Cover in my last talk in TR to Ruby on the browser which you can
00:05:42.680 find on YouTube if you want it's recorded and available on YouTube with that same title uh so basically the
00:05:49.919 first thing is you want to improve developer productivity with an isomorphic uh application so uh that
00:05:57.800 enables using the same programming language anguage on both the front end and back end to minimize friction and
00:06:02.919 maximize flow and creative problem solving so when you have a code base that's fragmented between multiple languages that slows down productivity
00:06:10.000 and creates friction whereas if you have everything in the same uh programming language and it has to be a very good
00:06:16.360 programming language of course and Ruby is a very good programming language then that improves productivity and it in in
00:06:22.440 my experience it could even double productivity um we want significantly
00:06:27.960 better front-end code readability and maintainability Via Ruby Ruby's unique syntax features like Ruby blocks and
00:06:34.520 operator overloading which are not available in JavaScript uh so things like this allow you to write a much
00:06:41.400 shorter and more expressive code in Ruby than any code you could write in JavaScript so that means the code
00:06:48.039 becomes more maintainable that means it's it's cheaper to fix bugs it's cheaper to add features uh it's quicker
00:06:54.680 to uh develop features as well so uh JavaScript is just in general an awful confusing programming language it's
00:07:01.000 famous there's a famous story about it getting developed in about 7 days or 10 days when uh when the first web browser
00:07:07.199 was created by Netscape if I remember right and uh so it's not a language that
00:07:12.479 was very well thought out and to this day because they try to keep backwards compatibility we we there are a lot of
00:07:18.639 nonsensical things in JavaScript that we suffer from uh also if if you're writing
00:07:25.240 a code like this even with the latest ecma script releases this code could be
00:07:30.599 improved in Ruby so if I rewrite it in Ruby there it is it's just two lines of code um you can even put them on one
00:07:36.840 line if you want but it's it's about two lines of code compared to uh that many lines of code so Ruby is a definitely a
00:07:44.440 game changer because it'll if I'm writing half the code or even less I'm like doubling my productivity it's that
00:07:50.759 simple which is huge for any company that want to compete in the market against their
00:07:56.039 competitors uh Ruby's ability to build declarative internal dsls to write lightweight front and guey code that can
00:08:03.240 mix logic unobtrusively uh will enable you to adopt a one language approach instead of
00:08:09.919 the confusing mixed of JavaScript HTML jsx templates Etc so there there is a
00:08:16.560 library uh written on top of opal Ruby called ineta where somebody created a DSL and Ruby for the front end that lets
00:08:22.960 you write the code similar to this where you can say div do food ingredients and this becomes a class it's kind of like
00:08:29.039 saying div class attribute food ingredients and when when I do this it
00:08:35.080 it opens the content of the div and then you can put stuff in so I can put a header declaratively I can put a UL
00:08:42.719 inside it and then Lis that are generated with logic and I can add if statements directly so unlike Erb where
00:08:49.080 you have to open a scriptlet we don't have to open scriptlets anymore here it's just you are in Ruby already you
00:08:54.720 can just add Ruby logic immediately when needed uh you can do each iterator iterators you could do whatever you want
00:09:01.160 in Ruby uh there's no more need for scriptlets like in Erb and also jsx forces you to like use Cur a lot of
00:09:08.320 curly braces to mix logic with structure here we don't have to do that we are in the same
00:09:14.720 language so this code becomes this once it's translated into HTML that is mounted in the browser in the Dom of the
00:09:22.200 page that you're seeing uh so yeah use JavaScript libraries from Ruby uh with enhanced
00:09:28.720 Ruby code having higher readability maintainability and flexibility so I mean there is a library called jQuery
00:09:34.040 opal that lets you use jQuery from Ruby using Ruby code so I can say uh document
00:09:40.720 ready that means on document ready I want to execute this code and here I can
00:09:45.880 element is like the dollar sign in jQuery so we're writing more English like Ruby code that's a lot more
00:09:52.480 readable uh in Ruby now that's doing the work of jQuery but also we're mixing it
00:09:58.000 with some of the Ruby Capac abilities of doing iterators like reject select Etc
00:10:03.480 um so it's a it it improves readability maintainability and
00:10:08.839 flexibility uh also it enables us to reuse some ruby gems on the front end which is great um and Ruby uh also has
00:10:16.839 better core apis in general than JavaScript like the apis for array hash innumerable string symbol
00:10:23.399 Etc uh Ruby's metaprogramming facilities are generally Superior to those of JavaScript uh like you can you know for
00:10:30.920 example we have rspec in Ruby that lets you write tests in a very english-like way there is a version of rspec for opal
00:10:37.160 Ruby actually so there's an opal arpec as well that's similar to this uh and we
00:10:43.360 can save development Time by sharing reusing rubby code between the front end and the back end that's a very big one
00:10:49.040 right now nobody who's using react or angular or anything on the front end with JavaScript is able to in general
00:10:55.639 reuse ruik code from the back end as is whereas here you can actually if I have code that contains Logic for calculating
00:11:02.360 taxes I can reuse the same exact Ruby code in the front end and calculate them instantly in the browser in front of the
00:11:08.600 user without having to reimplement everything in JavaScript so that's another productivity booster that would
00:11:13.680 save time and uh shorten the time to for delivery uh transfer developer skills
00:11:20.480 Ruby skills from the back end to the front end so there are Ruby developers that are more comfortable in Ruby on Rails and Erb and they might want to
00:11:27.320 transfer their skills to the front end well if you're using a a frontend ruby technology then they can they can do
00:11:32.720 that now so um so that covers uh the benefits
00:11:38.240 of trans like uh transitioning from JavaScript to Ruby but what are the tradeoffs uh it's always good to think
00:11:45.079 of the trade-offs as well so JavaScript uh cannot reuse backend Ruby code uh
00:11:51.279 however and and also it has inflexible syntax that makes it tough to write dsls
00:11:56.440 so it forces developers to use things like HTML L jsx templates mustache templates Etc because the the language
00:12:03.519 itself is not flexible enough to enable me to write dsls within it so that I can uh avoid using those templating
00:12:10.920 languages uh browser debugging has a onetoone mapping to the code however so
00:12:16.000 that's that's a plus so the first two are minuses this one is a plus uh when I open JavaScript code in the browser it's
00:12:22.720 usually a onetoone mapping to the code however that's not 100% true because if I'm using the latest version of
00:12:27.959 ecmascript in compiling it to an older version of JavaScript uh then by default
00:12:33.959 the one-on one mapping will break but fortunately browsers support a feature called Source Maps so it Source Maps
00:12:41.639 enable you to keep the one-on-one mapping um however JavaScript does not
00:12:47.440 enable full transfer of Ruby skills from the back end because it's a different language uh but it's natively supported
00:12:53.360 by web browser but that's again not 100% true if you're using a newer version of ecas script that's not not fully
00:12:59.160 supported by browsers yet however uh Ruby and the and the browser by comparison uh can reuse backend Ruby
00:13:06.160 code it has a very flexible syntax and the ability to build dsls that lets you mix structure and logic in one
00:13:13.680 language uh browser debugging does not have a Ono one mapping however with Source
00:13:18.920 Maps you would still have onetoone mapping so actually when I debug Ruby code in the front end using opal Ruby it
00:13:26.160 the browser opens the exact Ruby file that I wrote in the back end that I served from the back end sorry and I can
00:13:33.079 debug exactly the Ruby code that caused the problem so I don't ever have to do the debugging JavaScript even even
00:13:39.040 though I'm using a ruby to JavaScript transpiler because of using Source Maps so it's not a real problem it does
00:13:45.120 enable full transfer backend Ruby skills uh it requires server compilation
00:13:50.360 and download however so JavaScript if I'm not using the latest EAS script I
00:13:55.839 can get away without compilation with Ruby uh uh something like opal Ruby I do
00:14:01.120 need a server side compilation uh so yeah let's get started
00:14:07.120 by talking about uh glimmer DSL for web so the last during the last talk six months ago I I ended the talk by
00:14:14.000 mentioning a future project that I was working on called glimmer DSL for web that would enable people to use a ruby
00:14:20.720 DSL for building uh web front ends completely in Ruby uh and the technology
00:14:28.000 is very uh feature complete for building front end uh uh interfaces to a point
00:14:35.120 where I can replace react completely with this by and I end up writing half the code at least at most or something
00:14:41.320 like that I'll get into that in a second so it's a ruby in the browser web frontend framework so I kind of like how
00:14:46.880 there are a lot of JS Frameworks like vue.js uh react angular velt Etc this is
00:14:54.120 a ruby in the browser web front endend framework uh and it runs on opal Ruby
00:15:00.040 today in the future I'm I'm gonna explore running it on wasm as well wasm
00:15:05.399 Ruby so that way it becomes uh platform independent in the front end but for now
00:15:11.440 it's uh I'm starting it on opal Ruby because oper Ruby downloadables are only in kilobytes whereas wasm requires you
00:15:18.399 to download 10 megabytes if you want to use it so I did a a quick experiment with
00:15:24.519 this so I spent one weekend recently taking uh a web page from our web
00:15:31.800 application uh at leop and rewriting it completely in a glimmer DSL for web and
00:15:37.319 the web page is written in react originally so originally this one web page the so the one web page had a table
00:15:44.959 it had pagination it had sorting support for the table and it had filters for the
00:15:50.000 table so think of it as a as a very like basic table basically that is completely
00:15:55.440 uh fully featured for what tables expect which is Pion naations toring and filtering uh so the original code in
00:16:02.399 react it was like one giant file that was written with 523 lines of JavaScript and jsx code when I refactored them and
00:16:10.519 rewrote them in glimmer DSL for web and pure Ruby and and Ruby sorry it be like
00:16:15.680 the front and view component became 40 lines of code a tenth of the of the lines of code that was originally there
00:16:23.120 however uh the the problem with the react code was that react encourages you to like do State Hooks and effects but
00:16:30.680 the problem with State Hooks and effects is a lot of the time people will abuse them and mix a lot of business logic into the view component and it becomes
00:16:37.600 like a mess so the nice thing about Ruby is it enables you to just do basic object-oriented programming like so I I
00:16:44.240 felt like I can breathe again normally I can just do MVC and MVP so I just like
00:16:49.880 refactored the presentation logic to a presenter the model logic into a model and there's also an API class that will
00:16:56.920 handle talking to the server for API ey calls and that's it and then the view component became just view and it became very clean I'll show you an example of
00:17:04.079 that in a moment but basically by doing this I Shrunk the total code from
00:17:10.079 originally 523 lines of code to 296 lines of code so that's about 56% so
00:17:16.919 about half so I kind of like half The Code by switching from this technology to that technology but not only that
00:17:23.959 it's actually much more maintainable and readable and well organized code with better separation of concerns so not
00:17:30.520 only is it half the code so that that means you can finish features at half the time but also I can maintain it in
00:17:37.200 half the time and and like much more simply um one of the problems with react
00:17:44.559 is although they support components by the way glimmer DS sare web does support components too components is a very old
00:17:50.600 feature like react acts sometimes like they invented it but they didn't invent it components have been around since the
00:17:56.039 '90s at least uh but um the thing about react is the way it makes people mix
00:18:02.880 effects in state with the with the view logic tends to encourage developers to
00:18:09.039 mix a lot of logic with components which then makes components less reusable so we had a problem at work where every
00:18:15.520 time I needed a drop down it had the Lo business logic of what that drop down was displaying and if I wanted to use it
00:18:21.080 somewhere else I saw that like unfortunately one developer would would copy the past the code and paste it like
00:18:26.960 five times like place they needed to use it because although react gives you components if you're writing them with
00:18:32.919 hooks and effects in a way that's not well separated of concerns you end up
00:18:38.559 having to duplicate that code if you want to use it elsewhere uh whereas this encourages better dryer like drier code
00:18:45.200 that M makes that one drop down reusable cleanly without any business logic mixed
00:18:50.400 in it now I'm going to show you codes in a moment so here's the first example hello form MVP so this is a form that
00:18:57.960 follows the MVP pattern which is a variation of MVC meaning model view presenter which is kind of like model
00:19:03.520 view controller so it has validations as you saw so I enter a name I enter an email I add contact and it adds it but
00:19:10.760 it's validating along the way um and that's it it just fills the
00:19:16.640 table so it's a very simple example but see I'm using HTML validations which is
00:19:21.679 a feature that's already available in browsers so a nice thing about glimmer DSL for web is it already leverages
00:19:27.080 everything that you already have in standard HTML in CSS so that way uh you
00:19:32.880 write more standard code but in Ruby instead of JavaScript um so it's a very simple example so let's jump into the
00:19:39.120 code and how how it's written so the top level component is simply a hello form
00:19:44.600 MVP component so it's just a ruby class you include this uh module into it
00:19:49.720 glimmer web component and that makes that class uh represent the hello form MVP app uh as a as a full component and
00:19:58.039 the markup of it is basically declarative uh and this is real declarative not not like lying
00:20:04.799 declarative like in react and react they tell you declarative but you always say render the word render is imperative by the way like I mean I have a soft a
00:20:11.960 masters in software engineering I I'm pretty sure I know what imperative is versus declarative and react is half
00:20:19.280 imperative because you have to say render here I don't have to say render I'm really declaring the markup of that element and then I I Nest elements
00:20:26.280 within the markup so I say uh so by the way markup is taken from the word HTML which is uh hypertext markup whatever
00:20:33.520 language uh so I have a div I have an H1 header a contact form an H1 uh another
00:20:41.480 header and another and another component which is the contact table so these two are components so that way uh just like
00:20:49.480 in react or or even HTML web components you can declare your own keywords and add them to the DSL so I have a contact
00:20:56.760 form and a contact table and as you see this code is very simple it doesn't have hooks and effects like Hooks and effects
00:21:03.600 is such a weird concept it's because it doesn't map to anything in real life like it Maps it maps to math not to real
00:21:09.840 life in real life when when I'm thinking of a business app I don't think it's Hooks and effects I think of you know
00:21:15.919 give me a form give me a table give me stuff like that and here um and then all
00:21:21.679 the presentation logic and the model logic is handled by the presenter so the and the presenter will delegate to a
00:21:27.840 model as well it doesn't do all the work on its own but basically before rendering I I initialize a presenter so
00:21:33.880 think of this as a Constructor this method is kind of like the Constructor uh we build a presenter and then I can
00:21:39.640 use that presenter and pass it to the contact form and contact table and given that it's objectoriented programming
00:21:44.799 presenter is a full-fledged object it's not just State hook or something weird like that it's a full-fledged object
00:21:51.200 that houses the entire intelligence of presenting so that I don't have to worry about it so this gives you true abstraction like react reason ing about
00:21:58.480 react code that is like this large with a lot of hooks and effects it's very tough because you always have to keep
00:22:03.960 the context of everything in your head on every render statement here there's no render statement first of all uh
00:22:10.480 rendering happens implicitly when I declare the markup uh but also I don't
00:22:15.559 have to keep everything in my head at once I just have to think about what I'm seeing on the screen so we're seeing uh
00:22:21.760 you know this header contact form we have the the contact form itself and then we have another header contacts
00:22:27.320 table and then the contact table itself that's it and that's what you see is what you get basically so it's the
00:22:33.039 simplest code possible um so if we move on next this is the contact form view
00:22:41.240 component so it's very similar again it's a class it mixes in glimmer web component it receives one option uh so
00:22:48.960 option is basically the attributes that you can pass to a component uh you know in like I I noticed in react apps people
00:22:55.760 end up passing 15 attributes sometimes s because they're all like lowlevel attributes that are at a lower level
00:23:02.279 than object oriented programming so a lot of the time people don't think in objects in react they think more in like
00:23:08.640 like State uh State Hooks and that complicates everything whereas here it's very simple I just have a presenter and
00:23:14.919 it handles everything for me just through object-oriented programming uh but the key thing is also I have a
00:23:20.279 markup block within the markup block I have a form and it's all HTML basically written in Ruby so I using a DSL so I
00:23:27.679 have a a form tag a div tag a label tag input tag uh etc etc let me
00:23:36.120 actually uh sorry yeah let me zoom out a bit okay and then at the bottom I have
00:23:42.120 one more div so so here I have the name field I have the email field and then
00:23:47.679 here I have uh the type submit input meaning the submit button which says add
00:23:53.400 contact and on click it does this work so Within components basically uh the
00:24:00.200 glimmer Ruby DSL follows the same exact standard as HTML so whatever is
00:24:05.559 available on HTML if you HTML gives you an onclick attribute here you have the onclick attribute too except it's a nice
00:24:12.080 Ruby code that that is in the same exact language as this code so unlike in HTML
00:24:18.799 where the onclick has to link to JavaScript code and you have to maintain it in a separate file and you cannot do what I'm doing here unless you mix in
00:24:25.360 JavaScript code into the HTML which is very ugly here here we don't have this problem it's one language structure
00:24:31.520 logic and uh Behavior so we don't have that problem at all and then when I
00:24:37.440 click the submit button I can just use the basic HTML Dom apis from Ruby so
00:24:43.399 what I one nice thing here that you don't have in re something like react is I can just take those U elements and
00:24:49.840 assign them to variables and then you can just work with them as like objects so even view elements or components are
00:24:55.760 objects so then I can grab this object which is a Dom element that is representing input and uh input in HTML
00:25:04.240 you um uh will give you a method called check validity that you can invoke in
00:25:09.640 JavaScript so here you can do the same thing in Ruby except in with Ruby uh standards so check Val validity would
00:25:16.559 follow the Ruby underscored convention but basically I'm using Ruby syntax where I'm saying for both of those
00:25:22.360 inputs I'm using the very convenient Method All which I like a lot and I'm saying if all of them are valid when you
00:25:29.640 when you call check validity which will return a buan of true if they're valid then here I can write code similar to
00:25:36.720 what you would write in JavaScript I'd say event prevent default meaning I'm going to handle the event uh don't let
00:25:42.279 anybody else handle it and um and then it it delegates all the work to the presenter so now the nice thing is I can
00:25:48.520 do real MVC or MVP so I can separate all the logic uh into a presenter and I'll
00:25:55.279 tell it add a contact that's it that's all I have to do it's the simplest code possible it doesn't get any simpler than
00:26:01.200 that and finally I I basically say put Focus back so again the input is an is
00:26:07.279 an HTML Dom element object and it gives me a focus method in in in JavaScript so
00:26:12.880 here in Ruby I can invoke the same exact API the same exact API is available in Ruby so I can say focus and when when I
00:26:20.520 focus basically if I go back here you'll notice okay so it validated because I I
00:26:26.520 didn't enter the right name so see if if I try to add a contact without it being valid it validates but
00:26:32.679 eventually as soon as it submits it's going to jump back to name so yeah see it jumped back to name that's because of
00:26:38.159 the focus call that I have over here um the last thing here is tile which I have
00:26:44.080 collapsed I'm going to expand it on the next slide so I just collapsed the logic and and expanded the style so here style
00:26:52.559 uh there is something called a glimmer DSL for CSS as well that comes with glimmer DSL for web it gives you a DSL
00:26:58.720 for writing CSS code in Ruby as well so that means I can write programmable CSS
00:27:03.840 with if else statements if needed so if you need to add logic to the way you're handling CSS you can do it in Ruby and
00:27:11.600 add IFL statements to your heart's content and build your CSS dynamically if you don't need that you can actually
00:27:18.559 split the CSS into an scss file and handle it outside of this app so just
00:27:24.320 like any with any normal rails app you can have CSS files in Java C files you can still have that with this uh so if
00:27:30.960 you don't need logic you can just keep the CSS out uh or if you do need logic
00:27:36.159 you could do it here or a third approach is you can keep common CSS out but have
00:27:41.399 specific CSS with logic in so you can also do a hybrid approach uh but the
00:27:46.559 nice thing about this DSL is it's programmable I can add IFL statements I can generate things with loops and
00:27:53.000 iterators Etc so it's a very uh flexible approach
00:27:58.200 um okay and here's the presenter so the nice thing about the presenter is this pure Ruby code now which is amazing like
00:28:04.640 this code is not even aware of the view the correct way of following MVC or MVP pattern is to make the layer below the
00:28:11.200 view uh unaware of the view so there's a view the presenter and the model or view controller and model the controller
00:28:17.480 presenter or model should not be aware of the view if if it's followed correctly by the way rails in the back
00:28:22.559 end doesn't follow it correctly because the controller pushes variables to the view which is not a not the correct
00:28:27.880 practice of MVP or MVC but it doesn't matter here we don't have to follow uh we can follow a better version of MVC
00:28:33.880 here uh so this presenter is basically a reflection of what we saw on The View
00:28:39.440 but at the at the logic level so we have basically contacts which are displayed in a table uh on initialization of the
00:28:47.000 presenter we fetch the contact so imagine this method not having man
00:28:52.080 static contacts this method would basically have an Ajax call and it would call to the server and grab the initial
00:28:57.799 list of contacts from my rails API uh backend uh route basically that's the
00:29:03.440 normal way you would do this in a in an actual page that's how I did it when I implemented a proof of concept in one
00:29:09.039 day in the week in a weekend uh it might have been a day and a half in a weekend recently so either way you we initialize
00:29:16.679 the contacts and then also we initialize a new contact that is used only for the
00:29:21.720 new contact form and then finally we have an add contact method and that represents what happens when we click
00:29:27.720 the button so uh new contacts will get filled when we're we're filling the input fields of name and email and then
00:29:34.399 when we click the button this method will get invoked and the the nice thing about this is it's completely decoupled
00:29:40.320 from the view all I have to do is take the contact and shove it into the contacts array and then I empty the name
00:29:47.320 and the email everything that's happening here will happen in the view automatically because we're using data binding which I'm going to get into next
00:29:54.360 but this here the code is very uh very uh clean of view concerns it doesn't
00:29:59.799 have it doesn't care I just all I have to do is put this here when you put this here the view will show the contact in
00:30:06.200 the table so so think of this as okay so now we're going to enter this datab
00:30:11.480 binding will copy this to that new contact uh object and then here it'll copy the email to the new contact object
00:30:18.720 and when I finally add the contact it'll shove it into an array and this table is
00:30:24.360 actually listening to the array I'm GNA show you that code in a bit so this table is listening to the array and as
00:30:29.480 soon as the array gets populated by the contact this will get populated and that's because of the the very uh
00:30:36.720 flexible uh Ruby meta programming facilities so those objects that I just
00:30:42.840 showed you um aren't even aware that they're being observed by The View uh
00:30:47.960 the nice thing about Ruby is you can enhance object enhan objects after we've created them so what we do here is the
00:30:53.559 view will Auto enhance the array and make it an observable array with without me having to worry about that here
00:30:59.480 whereas if you used older libraries of that use the MVC pattern in the past they would ask you to like make a
00:31:05.880 contact array that is observable here I don't have to do that you don't have to do any you just write pure Ruby like
00:31:11.240 simple Ruby code that is a simp a pure array um a real model Etc and everything
00:31:18.480 will happen for you automatically so it's all using the benefits of automation by the way contact is just a
00:31:24.720 struct in Ruby so uh I I can build a class I can have a contact as a class or I can make it a struct so the same
00:31:30.880 struct keyword that's available in backend Ruby is also available in front end Ruby so it's just a struct with name
00:31:36.279 and email and with keyword initial initialization um so it's very simple uh
00:31:43.639 finally here the contact table uh view is very similar except it's building a table in the markup so as you see I have
00:31:50.960 a table it's got a tad TR Etc the nice okay this is the part that is automatic
00:31:56.240 that I just described so this is called content data binding so what I'm saying here is I the content of the T body is
00:32:03.159 going to get data bound to the contacts on presenter this is where we actually
00:32:08.240 observe the view so we're using the Observer pattern implicitly and saying whenever contacts change on the
00:32:14.200 presenter I want the cont content to get uh updated as soon as this uh gets
00:32:20.840 updated so when we add the contact to the list of contacts or array of contacts this block will get executed
00:32:27.720 and then it will uh render this part so here we just take the presenter contacts and we Loop through them and we build TR
00:32:34.799 uh Elements which are just pure HTML elements and we we build TD elements within them which are basically the
00:32:41.000 table cells uh table data so and here I'll fill it with contact name and contact email so again this is like the
00:32:48.120 simplest code possible to do this doesn't get any simpler than that it's what what you see what is what you get and the only part that I that is getting
00:32:54.760 rendered that I need to worry about or think think about sorry as being rendered is the only part that we care
00:32:59.960 about rendering so uh like I mentioned one problem with react apps is react
00:33:06.039 will render everything so I always have to think keep in my mind the context of everything uh and it's true that they
00:33:12.519 use Virtual da behind the scenes to avoid updating everything in the dawn but still as a developer developers do
00:33:18.679 have to keep the context of everything in their head to make sure that if I update this part it's not breaking this
00:33:23.880 part whereas here only the part that's changing is the part that is getting rendered everything else is static and
00:33:30.240 stable so that means this Library does surgical updates so it doesn't have to worry about uh updating everything it
00:33:36.559 only worries it only updates what changes that's
00:33:41.679 it um so performance is pretty fast I mean I tested it with our work app and
00:33:47.679 performance was as good as what I had in react practically I mean react might
00:33:52.720 have been might still be a bit faster but it doesn't matter for our like business for a lot of normal business
00:33:58.840 needs this is fast enough this is very fast actually um so yeah so the last
00:34:04.000 thing that I need to cover let me see oh yeah the Styles so this is also a
00:34:10.000 CS whoops yeah CSS uh glimmer DSL for CSS one thing to
00:34:16.079 keep in mind is given that we're using a ruby DSL DSL these are behind the scenes implemented as methods uh so this method
00:34:23.000 border spacing in CSS it has a dash any that's Dash in CSS becomes underscore
00:34:29.000 and Ruby that's the only thing you have to translate in your head otherwise this those uh rules so the reason we have R
00:34:35.639 is it's a rule every block is a is a rule and I I can use the word rule if I
00:34:40.879 want but I provide an alias which is just R if in case you want to use the Alias instead because the Alias is just
00:34:46.919 shorter but yeah this is again CSS for the table um so yeah now that I went
00:34:52.520 through a full-fledged example that covered almost everything thing uh yeah
00:34:58.119 almost everything in the glimmer DSL for web uh let's dig down into what are the ba the glimmer Ruby HTML DSL Basics uh
00:35:06.280 one thing though that I left out that I skipped over sorry very
00:35:11.480 quickly is so I covered uh content data binding over here but I did not cover
00:35:19.240 standard Property Data binding so let me go back into standard Property Data binding so here when we have an import
00:35:25.040 field for text and for email uh as you notice not only do I have attributes set
00:35:32.960 here for the HTML elements like type ID required autofocus which lets you leverage all the features of HTML like
00:35:39.640 HTML validations but also I can open a Blog and add um data binding statements
00:35:46.520 within it so here I'm saying I want the value of the input to be by directionally datab bound use so using
00:35:52.960 Ruby operator overloading we can I can actually just use the Double Arrow
00:35:58.400 symbol to very fluent like expressively say that I want two like two by two
00:36:04.560 directional data binding that will connect any changes that happen to the name on the new contact model to the
00:36:12.920 value of the input so that means when when the user types anything into the
00:36:18.000 text field it'll automatically get copied into the name of the contact and if I go and update the name of the
00:36:25.200 contact and clear it so as you saw in the presenter
00:36:30.880 um here after adding the contact I actually clear it I say take the name of
00:36:36.760 the contact take the email of the contact and set them both to empty string as soon as you do this the change
00:36:42.960 cop goes to the other direction so that's bir directional data binding so you have like Ruby gives you a very
00:36:49.599 unique version of data binding that's unavailable in any other JavaScript framework um so that's what that is so
00:36:56.079 let's get into to um glimmer Ruby HTML DSL Basics so for example you have an
00:37:01.200 HTML document so uh so yeah glimmer Ruby HTML sorry the glimmer Ruby HTML DSL
00:37:08.720 enables building web user interfaces with a ruby embedded or internal domain
00:37:13.800 specific language so a DSL is a domain specific language uh can anybody here
00:37:19.400 explain what a DSL is for others who don't know what a domain specific language is somebody provide an example
00:37:26.200 or an exp explanation just to have some audience participation okay go ahead
00:37:34.359 Thomas if you could speak a bit louder so so it's recorded on the mic in Wales you have like has many associations that
00:37:42.160 in Wales right so it's not Ruby itself but it's a language created out of Ruby
00:37:48.240 to make your world simpler and Abstract all the internal so you don't have to do
00:37:54.200 it yourself yeah exactly so dsls let you create a language that's internal or
00:38:00.280 embedded within Ruby meaning a language within a language uh that lets you
00:38:05.520 pretend that you're in a in a specific domain so what what what Thomas just mentioned which is has many associations
00:38:11.480 or belongs to Etc and rails that lets you define the domain of uh
00:38:18.640 relationships and associations and relational databases so that's what has many or belongs to is whereas here uh
00:38:26.079 the domain is building uh a user interfaced HTML document so that's why
00:38:31.160 here it's an HTML DSL so that's the focus of this DSL and it lets us use keywords that are from the HTML domain
00:38:38.040 as you saw already there would like I was able to just say form input label uh
00:38:43.359 button Etc anything table TR TD everything that's available in HTML is now available in a domain specific
00:38:49.400 language within Ruby so yeah you can say HTML uh actually sorry let me cover the
00:38:56.079 the bullet points first so element keyword so first let's start with number one the the number uh the first concept
00:39:02.720 is element keywords meaning this DSL the first thing you want to know about it is ele what are elements or element keyword
00:39:09.280 so keyword means uh what is the word that's representing the element so you can have an element called input for
00:39:15.160 example so the keyword is input and in Ruby though it's underscored case so it does follow the
00:39:22.160 Ruby conventions uh it's a declarative way of building HTM L uh so declarative not
00:39:29.359 imperative the imperative way for example like in Java Swing apps if I'm building a user interface imperatively I
00:39:35.160 have to say uh uh composite add uh
00:39:40.640 control or add something and I would add a control within the composite like I can add an input field within a div for
00:39:48.000 example I have to say it imperatively I have to say div. add this that's imperative whereas here it's declarative
00:39:55.319 I just put a i just put the elements within each other kind of like in HTML and Ruby uh glimmer will automatically
00:40:02.640 infer the structure you're building in HTML F declaratively without you having to say add this and add
00:40:09.560 that or append this or prepend that so uh and behind the scenes it's just
00:40:15.119 they're just implemented as Ruby methods behind the scenes or they call them in Ruby they call them messages Ruby messages so yeah you can have a keyword
00:40:22.520 like HTML head body form input label select option table Tad tbody TR t h TD
00:40:32.240 we saw all of those already H1 H2 H3 section o o ordered list unordered list
00:40:39.359 list item uh division or whatever span uh p as in paragraph strong
00:40:47.920 emphasized or you can build your own components so I can make my own new keywords and add it to the DSL so I can
00:40:53.640 have address form like I already showed you examples of that contact form I just showed you that contact table uh
00:41:01.280 Etc and by the way contact form and contact table if I were to go back to their element
00:41:07.000 declaration uh they uh so glimmer tries to do convention by configur by sorry
00:41:13.359 convention over configuration just like rails as much as possible so the convention here is if I build a class in
00:41:20.720 Ruby and I mix into it glimmer web component it'll automatically take the name of the class and or it so now I
00:41:27.720 have a an a component called contactor form so as you saw in the first page
00:41:33.240 when I used it contactor form so automatically glimmer will handle this for you you don't have to do the work
00:41:39.280 yourself all you have to do is declare a class and whatever you use for the name
00:41:44.319 of the class uh in camel case will get underscored and will become the underscore keyword underscored story
00:41:50.520 keyword that you can use in the HTML DSL by convention so uh so yeah that's
00:41:57.760 that's the first concept you need to learn is element keywords so let's move on to the next
00:42:04.240 concept by the way there's a full list of HTML elements on this link I am going to post the slides on the meetup.com
00:42:11.240 page uh after the event uh so you'll be able to click on the slides and click on
00:42:17.000 this link and that'll give you a list of all the HTML elements but a lot of you are probably already familiar with them from your work in JavaScript and
00:42:24.400 HTML uh the next concept is element arguments so you can pass elements uh
00:42:30.280 elements arguments in Ruby and the arguments either constitute attributes that are in a hash or keyword arcs or
00:42:38.160 text content if it fits on one line so they're actually optional you don't have
00:42:43.440 to have arguments but if you do pass them the first argument optionally can be a string string content if it fits on
00:42:50.680 one line so if I have an H1 U uh basically header and the content of it
00:42:56.480 this content form you can just pass it as a string as the first argument uh the rest of the arguments
00:43:01.880 are a hash of HTML attributes or a different way of thinking about them is their keyword arguments using the newer
00:43:07.119 versions of Ruby which uh I mean Opa Ruby runs Ruby 3.1 if I'm not mistaken
00:43:12.280 so it does support keyword arguments but yeah this is basically me passing both the first argument and the hash or the
00:43:19.920 keyword arguments which contain an ID attribute and a class attribute and the values are just strings in this case uh
00:43:27.559 so it's very simple and both of them are optional so I can drop the the string content if I want and just have the hash
00:43:33.440 alone so this example input has only just the keyword arguments or the hash or basically the attributes uh so that's
00:43:40.920 about it it's very simple that's the second concept you need to learn about this HTML
00:43:47.079 DSL um okay so the third concept is the content block block so Ruby gives you
00:43:53.440 the feature of Ruby blocks and when we writing Ruby blocks over multiple lines
00:43:58.760 usually you say do end like for each element in this array do and then you you write some logic inside the do end
00:44:06.000 block and then you say end at the end uh here intentionally because we're we're in a DSL within Ruby we're not going to
00:44:12.880 follow the conventions of Ruby for multi-line blocks we're going to follow the conventions of glimmer of the glimmer HTML DSL which recommends using
00:44:20.200 curly braces because curly braces are declarative do end is an imperative statement when you say do that's
00:44:26.000 imperative when you're just putting braces and saying okay this is the content this is a a declarative I'm just
00:44:31.720 declaring the content so it's recommended to use curly braces not do end here uh by the way we will use dend
00:44:37.599 for things that include uh that use imperative logic and I'll show you that in a moment like listeners for example
00:44:44.559 uh so those are useful for declaring properties kind of like I showed you we declare the value property for input and
00:44:50.599 we data bound it to uh an attribute on a model so we can declare properties
00:44:57.000 or event listeners or nested elements so I can put a TR inside the table or t
00:45:02.839 head or whatever uh or I can put string content within the content block as well but it
00:45:08.599 has to be the return value meaning the last thing that's returned from the Block if the last thing returned from the Block is a string the glimmer DSL
00:45:15.760 for HTML will automatically infer that that is what you want as the content of the element and will generate HTML
00:45:22.680 without that being the string uh being the content of the element and I'll show you examples of that in a bit but let's
00:45:29.599 go over the first one the first one is properties so HTML Dom elements have properties like if you go on the web on
00:45:35.800 the sorry on on the internet you can find uh the API of the Dom and what
00:45:41.720 properties you have on an on on on on Dom elements or Dom objects and one of
00:45:46.880 them is inner text however here will follow the Ruby standard for it inner underscore text but in in JavaScript it
00:45:53.000 might have been inner and then capital T text either way in text is a property that you can set on any element to
00:45:58.640 update their content with text that you want so if I want I can set the text using in text the inner text property
00:46:05.640 that's one example another example I just showed you is we can uh set the value property so that's another example
00:46:13.359 so there are you can also set the ID you can set the class name um you can set the style there are a lot of properties
00:46:20.000 you can check them all here on this W3 schools website uh the next thing is event
00:46:26.440 listeners so I already showed you an example of that you can just say onclick do end okay so here we're doing we're
00:46:33.839 finally getting into imperative code so imperative code is not all bad the way we get work done in any programming
00:46:40.640 language is using imperative code uh imperative code is what lets you write logic with if statements or iterators or
00:46:47.040 stuff like that in the end you have to do some logic uh however the nice thing about the glimmer DXL is it segregates
00:46:53.960 logic from structure so if I'm within the structure of a button I use a curly brace and I put other elements within
00:46:59.920 button and properties and stuff like that and a listener but once I'm saying I have an onclick listener then here I
00:47:06.640 say if onclick once it's clicked do this work so this is imperative code so it's a very clean separation of concerns that
00:47:13.680 way you can always tell logic away from structure and it achieves it makes the code very very maintainable so here
00:47:19.839 we're saying once we click the button we it'll uh do uh it'll print an alert popup basically and dollar dollar in uh
00:47:27.680 opal Ruby gives you access to the top level element in JavaScript like the global element so this lets me then call
00:47:34.040 alert uh and then say hi so Event Event listeners always begin
00:47:41.040 with the on prefix uh they follow the Observer pattern they're an imperative code block
00:47:48.240 that's it and I just showed you an example here's another example which we we saw earlier uh so I mean in this example we
00:47:55.079 take two uh input uh objects we check that they're both valid and if they are
00:48:00.200 then we handle the element we delegate work to the presenter uh yeah we delegate work to the presenter for
00:48:06.640 adding the contact and then we refocus the input element that needs refocusing
00:48:11.680 so that way like at this layer the logic is mostly view level logic and most of the model level logic is handled in the
00:48:19.559 presenter uh so yeah and event listeners um there there's a full list of event
00:48:26.040 listeners at this page but you know on blur on click on change on on focus on
00:48:32.520 input Etc on Mouse up on Mouse down on key up on key down
00:48:37.920 Etc um the third thing is nested elements we already saw an example of that like a table that has a t head or t
00:48:44.160 body or or it's optional actually in HTML although it's better to have it you can also Nest things directly like that
00:48:50.200 if you want TR and the TD but either way uh this is a declarative hierarchy it follows the composite pattern the
00:48:56.960 composite design pattern uh is anybody familiar with design patterns by the way in software um are you familiar with the
00:49:04.480 composite design pattern I remember yeah the composite design pattern is basically U tells you that uh objects
00:49:11.680 could be modeled as uh composits and leaves and any object that is a composite can be composed of other
00:49:18.559 objects whereas any object that is a leaf cannot contain anything so for example an input element um usually will
00:49:25.799 not have anything nested underneath it however a div will have many things nested underneath it so that's a
00:49:31.000 composite pattern so that's what HTML is actually an application of the composite pattern and here we have HTML in the
00:49:37.079 Ruby DSL so it's the same thing here's another example which we saw
00:49:42.920 already okay the last thing is string content so if you want you can put string content as the return value of
00:49:49.079 the block that the nice thing about Ruby versus other languages like uh JavaScript is uh I mean JavaScript they
00:49:56.160 try to copy Ruby that a bit if you have a on line thing but if you have multi a multiple line function usually you have
00:50:02.559 to have a return statement in JavaScript whereas here we don't in Ruby so then I can write a nice DSL that's fully
00:50:07.960 declarative there's no imperative code in it and I'm just declaring that flying cars become reality is the body of H1 so
00:50:15.720 then it'll render it as the content of H1 uh it has to be the last thing if you
00:50:21.280 have multiple things within the H1 uh one thing to keep in mind though as an alternative you can put it as the first
00:50:27.960 argument as I've explained earlier if it fits on one line but this is more useful if it fits on multiple lines so let's
00:50:33.880 look at a more realistic example for multiple lines so if I have a par paragraph it's often uh used for writing
00:50:39.720 paragraphs which are multiple lines this is how you do it it's a very nice DSL for doing it and if you want to embed
00:50:46.520 other uh things within it like a throng if you want to make part of the text strong meaning bolded or you could
00:50:53.359 Define it any way you want in CSS or this is emphasized then I can actually
00:50:58.400 use Ruby string interpolation and just add uh use other uh HTML DSL keywords to
00:51:05.839 embed basically things within the string that's going to get returned as part of the P that's just an alternative way of
00:51:11.200 doing it so you could do it this way or you could do it that way I actually moved the double quote up just to get it
00:51:16.599 out of the way so it's very convenient and very productive in Ruby
00:51:23.640 uh the final concept you need to know the fourth one is element methods so they're basically invoked through their
00:51:29.160 underscore Ruby methods they match the HTML Dom element API they proxy calls to WRA HTML domum
00:51:37.760 objects they include access to element properties after construction so for example I showed you the benefit that we
00:51:44.680 don't have in other things like react which is being able to assign a view object to a a variable once I have it as
00:51:51.920 a variable then now I can call methods on it so these are element methods and they follow exactly the same API as the
00:51:58.280 Dom API in JavaScript so I can check validity I can take the value or I can ask the element to focus so that's what
00:52:05.359 I demonstrated earlier uh there are also a few extra
00:52:10.960 API methods that are available in glimmer only like content so glimmer gives you a method called content that
00:52:16.280 lets you reopen the block the content block of table and add more things so if
00:52:21.359 I constructed a table originally with only the heads the headers I can later open it again and add uh a a row below
00:52:30.079 the header so you can always reopen any element you want using content and add stuff in it it's a bit similar to Ruby's
00:52:36.799 idea of open classes where you can always re openen a class and add more methods to it here you can always reopen
00:52:42.200 an element and add more content to it uh so yeah HTML Dom element methods
00:52:48.920 are available at this web page so let's get deeper now into how we
00:52:54.680 T we we use all of these Concepts together so usually you want to follow the MVC software architecture or a
00:53:01.040 variation on it the proper MVC architecture usually will have a view that is observing the model for changes
00:53:07.520 which I did earlier using datab binding um and as soon as the model is updated
00:53:12.760 uh like we update the name of the cont new contact The View will will take that
00:53:18.119 update it'll receive the model updates and it'll refresh itself and correctly clear the name input field
00:53:26.000 um and then the controller and it has to be this like usually the view will
00:53:31.119 update will observe the model and the model should not be aware of the view which is exactly what I showed you
00:53:37.119 earlier the model was not aware of the view the content also will observe the view for changes and will U manipulate
00:53:45.079 the model uh sorry the controller not content the controller in that in our case was basically the event listener
00:53:52.200 block so it's an implicit controller you don't have to declare explicit controllers like in rails I'll show you
00:53:57.799 what I mean in a second so here if I have an onclick uh onclick keyword and
00:54:03.319 then I have a block this block is the controller it'll basically rece observe the view and as soon as something H like
00:54:09.839 the button is clicked the submit button it'll execute this code so this is basically the controller uh which is
00:54:17.079 this block observing The View and when the when the event happens then it'll
00:54:22.880 delegate work to the control the model in this case the model is the presenter um so the presenter actually is a bit of
00:54:30.000 a gray area presenter is both controller and a model but I I'll get into that in a
00:54:37.720 second so this is proper MVC which is even more correct than the MVC that's
00:54:44.119 applied in rails uh which achieves uh much better separation of concerns and
00:54:49.240 maintainability for the code and and it makes it more productive to build new features um
00:54:55.760 and the Observer pattern basically I just described The Observer pattern already and gave you examples of it but
00:55:01.760 also glimmer gives you the keyword uh observe in case you want the view to explicitly observe the model without
00:55:08.040 data binding so I can either observe the model with data binding like I showed you earlier or I can use the observe
00:55:13.440 keyword and observe the model without datab binding to observe an attribute on a model for changes and then I would execute a block once a change happens
00:55:21.079 I'll show you examples of that in a moment well I mean let's look at hello Observer so hello Observer has two
00:55:26.440 fields that are bound to the same value so there's a number that's it the value is just a number and it could you can
00:55:32.480 either manipulate it with a spinner or you can manipulate it with a slider and they have to stay in sync so um to do
00:55:40.039 that basically we have a model called number holder the model just has one attribute number it initializes it to 50
00:55:47.799 on start that's it that's the model uh and what we want is both this and this
00:55:54.000 view component to monitor the model for changes and reflect them in the
00:55:59.720 view so this is the hello Observer glimmer web
00:56:04.760 component so there are two new blocks that I haven't showed you before before render and after render I'll get into
00:56:11.359 them in a second but first actually I showed you before render but I haven't showed you after render whoops sorry I
00:56:18.160 messed up okay so the markup though is what matters the most in the markup we have a div within the div we have two
00:56:24.599 divs and the first one has the input uh field that is of type number uh so input
00:56:31.280 of type number is basically spinner is what I showed you as the spinner the one on top then second one is input of type
00:56:37.440 range which is a slider so we're using standard HTML nothing fancy as far as
00:56:42.680 that um that's the nice thing about this you could just use standard HTML but on the the first one on input meaning on
00:56:49.599 changes to it to the to the value it basically will take the number holder model and and update its number
00:56:56.000 attribute to the value of that input field so I can use the variable that
00:57:01.839 I've assigned earlier and use it within the listener here uh so it's very intuitive and straightforward like if
00:57:07.720 you like to think in of things in terms of variables like you normally do in Ruby you can do that here too um and
00:57:15.039 here we do the same thing we also grab the variable that by the way the benefit of variables also is unlike jQuery which
00:57:21.880 forces you to always use an expression for an or a CSS class to grab an element
00:57:27.240 here we don't have to do that you can just assign the element to a variable and just use the variable you we almost never ever have to use a CSS uh
00:57:34.799 expression to grab the elements so it's a lot the code is a lot simpler and glimmer but the key thing is either way
00:57:40.960 if I change the input here or here it'll update the model number uh now if you do
00:57:48.039 that then if I change number here it'll update the model but this wouldn't get
00:57:53.400 updated the way to have the other view component get updated is it has to observe the model so that's the other
00:57:59.680 part of MVC is the view has to observe the model as well so to do that here in
00:58:04.839 the after render block which executes after you built the the markup elements
00:58:10.440 this will lets you uh attach observers after you built the the user interface
00:58:15.799 so then I can attach an observer on the number attribute on the model and say if this changes fire this block do this
00:58:22.640 work and here it'll do this work and'll basically go and grab the first the number input and update its value from
00:58:30.680 the model and then it'll take the range UT and updates value for the model unless they're already set if they're
00:58:36.599 already set to the same value it will not change them but that that'll prevent uh an infinite Loop uh but otherwise
00:58:44.359 it'll update them so the nice thing is this will end up making you uh be able
00:58:50.880 to reflect your changes in the other uh element without T touching the the other element so if I change this one it'll
00:58:56.960 change that one and if I change that one it'll change this one so this is the Observer pattern now
00:59:03.520 let's jump into something more advanced so MVP is an is is like an evolution of MVC or a specialization of it maybe
00:59:11.039 where the controller is upgraded into a presenter and the presenter decouples
00:59:16.480 the model from The View completely in a way where
00:59:21.599 um The View doesn't have to talk uh sorry so the presenter will listen to both sides and if one side changes it'll
00:59:28.799 update the other side and does it does that using bidirectional data binding
00:59:34.160 um so let's talk about bir directional data binding so the the basic version of
00:59:39.559 it is called Property Data binding and I already showed you an example basically if I have an input field and it has a
00:59:45.520 value I can bind it to the name of a contact and that way when the user types
00:59:50.680 something in that field the value automatically gets saved or persists Ed into the name attribute on contact and
00:59:57.079 if I change the name on contact it'll automatically clear or change the field in the view so it's a it's a very very
01:00:04.079 simple way of thinking about user interfaces in my opinion it's a lot simpler than using something like react
01:00:10.359 because you don't have to keep the context of a full method that's rendering anymore you just think about this tiny tiny little part that's only
01:00:16.039 just the value and the contact name and you just think the way I think about it is the way I write the code like in my
01:00:22.160 head I'm like I want this field to show me the contact name and when the user types something in it I want it to go
01:00:28.000 into the contact name well that's exactly what this double arrow says this is saying if if this changes copy it to
01:00:35.000 this side and if this changes copy it to that side so that's it it's the simplest thing possible to express this there's
01:00:41.799 also unidirectional data binding which is useful if you have a um a property on an element that is not uh that is read
01:00:49.359 only so uh or sorry um write only so in this case for example example I can
01:00:55.119 populate the div content like the inner text of a div uh from the text of of an
01:01:01.480 address model not only that unidirectional datab binding will also observe the model for changes and if
01:01:07.119 this ever change again it'll automatically copy it to the content of the div so that way that that that div
01:01:12.839 will automatically always update based on the address text um however the div
01:01:18.640 itself is not a control that gives you uh uh access to update the model it can
01:01:24.079 only show content but it doesn't let you modify content so that's why this is unidirectional data binding not
01:01:29.200 bidirectional so there are cases where unidirectional data binding sufficient there and there are other cases where you need bidirectional data binding uh
01:01:36.599 this is another example so there and there's also more sophisticated feature The datab Binding glimmer which I'm not
01:01:42.319 going to cover today but you can read about them on the glimmer project web page uh like for example I can install
01:01:49.160 um converters so here I'm saying I want to link the inner text of the button to
01:01:55.079 the count on a counter but also as soon as the count on the counter gets updated
01:02:00.119 on read of the property as soon as we read it and we're about to copy it to the view I want you to execute this uh
01:02:06.160 Ruby block or Lambda which will basically take the value and copy it and
01:02:11.319 put it in a string and then now the button is going to show the string instead so instead of showing the value
01:02:16.520 raw it'll show an updated version of it so you can use converters and the converter logic you can if it's very
01:02:22.200 simple you can put it in the view if it's comp at you can put it in a presenter or model and have that presenter or model handle it
01:02:29.359 instead um so now let's look at hello Observer that we just which we just saw earlier using datab binding it's a lot
01:02:36.200 simpler the code that we just wrote manually using observers explicitly is going to get Rewritten refactored into
01:02:42.920 Data binding and this will show you why data binding is such a such a such a how
01:02:49.640 do I say productive feature like productive um yeah very productive feature because it helps you WR a lot
01:02:56.039 less code so all the code that I wrote earlier that I just showed you got squished into those two lines so now we
01:03:02.480 only have this line that says monitor The View and update the model and also monitor the model and update the view
01:03:08.039 here it's the same thing monitor the view update the model monitor the model update the view and that's it we're done there's no after render I deleted the
01:03:14.640 after render we don't need it anymore we don't need to add observers manually anymore all of that is automated
01:03:19.920 automatically through datab binding so this does everything that we wrote we saw earlier so just to show you the code
01:03:25.839 from before this was the code before uh all of those lines of code this is the
01:03:31.000 code the same code with datab binding it's a lot simpler so I mean just imagine how much codes in a codebase
01:03:37.559 written with react or some other Library would shrink with code like this it's unbelievable like I already showed you
01:03:43.440 in a real application when I did an experiment it cut down the code to 50% or 56% of it so um this definitely is a
01:03:52.119 huge benefit in Ruby versus JavaScript script um the last thing about data binding that you need to learn is an
01:03:58.440 advanced version of data binding called content data binding um which basically lets you do
01:04:05.160 the same thing except you're updating the content of an element um and I already showed you an example of that
01:04:11.079 like the content of a table got updated as soon as we added contact a contact to a contacts array so it always lets you
01:04:17.920 monitor an attribute on a model which could be an array for example and when when it updates it'll render this part
01:04:23.960 only so again these are surgical renders like only the the part that changes renders
01:04:29.839 which is the way we think about it the the thing that I've always found weird about react is it renders everything and
01:04:35.400 it forces me to think about everything whereas here I don't have to worry about everything just the part that changes the part that it gets that's going to
01:04:42.160 get rendered I know there's virtual Dom and react to also do the same thing but
01:04:47.200 it's confusing still here it's not confusing it's very simple because the code is reflecting how we think about it
01:04:52.920 so here's a content datab binding example like I have an address form it's a very normal address form it's using
01:04:58.440 bidirectional data binding on all the fields and it has here unidirectional data binding to populate a summary of the address however as soon as I bump up
01:05:05.960 the spinner value here from one address to two it automatically rendered this bit and generated a second address form
01:05:13.880 because I have two addresses now I can add one more address boom it just added
01:05:19.319 one more address form so the nice thing about content datab binding is it enables us to uh rerender one part of
01:05:25.480 the page that's Dynamic while leaving other parts static so here's the code so on the top
01:05:32.440 I have the input field which is the address and the number of addresses count and it basically is using data
01:05:40.599 binding for updating the address count proper attribute on a user model and then here I open a div I just
01:05:48.000 say I want content data binding so I take the content keyword I say bind it to user addresses and as soon as that
01:05:55.160 changes this block will get rendered and then I can just iterate so I don't again
01:06:00.960 we don't have to open a scriptlets a scriptlet like an Erb or do something weird with curly bracelet like in jsx we
01:06:07.319 are already in Ruby so I can just immediately grab the user addresses iterate through them and render um an
01:06:13.640 address form basically by the way this code over here can be extracted into its own component if I want and in fact
01:06:19.760 that's what I did in my work application I extracted this bit into its own component that that is handled separate
01:06:25.960 in a separate file but still this is basically going through name Street City address zip and uh rendering a label and
01:06:33.000 input for each one of them again using standard Ruby iterators like each um and
01:06:39.039 then here at the bottom it it basically is rendering um a summary of the address
01:06:45.039 so that's the bit that was showing us a summary so as I'm typing here there's a summary of the address is showing up
01:06:50.520 here and that that's it so the number of addresses is basically uh getting
01:06:55.599 rendered with content data binding so this basically uh is what provides you
01:07:01.160 with this ability and glimmer so that's pretty much it for data binding we're done with that so uh
01:07:08.279 we're getting into the final part of the presentation which is uh glimmer web components so I already uh chose to you
01:07:15.680 know show you glimmer web components from the start with the hello form MVP example but let's get into them in detail basically you just declare a
01:07:22.559 class and mix in uh glimmer web component uh it generates a new Ruby
01:07:28.000 HTML DSL keyword like I already showed you that's an underscored format um the address for example an
01:07:35.520 address form class will generate address form keyword um you can Define options I already showed you an example of that
01:07:42.520 that can be passed as hash arguments you can define a a markup block which I
01:07:48.000 already showed you declaratively and you can have a before render and an after render block
01:07:55.240 one thing to keep in mind is this is not like react uh rendering usually happens only once that's it uh it doesn't
01:08:01.599 reender all the time the only places that get rendered again is are the places where you're using content data binding or Property Data binding and
01:08:09.240 Property Data binding doesn't render it just resets a property on an on a Dom element whereas content data binding
01:08:15.839 reenders but only but surgically only the tiny little part that's changing
01:08:22.359 um and if I have a class that I've declared as a top level component it has
01:08:27.880 a render class method that you can call in order to render and mount the component in the body of a document by
01:08:34.400 default or I can pass a parent option that will give and specify a CS selector CSS selector to mount the um a single
01:08:43.400 page application somewhere inside the HTML document so if I have a a website
01:08:48.520 that is like this part is rendered by Erb and then this tiny little part I want it rendered with glimmer because it's dynamic dnamic I can keep
01:08:55.440 everything in Erb but this one little div you can pass the CSS selector for it
01:09:00.799 like the ID and it'll render the compon the glimmer component within it only and
01:09:05.880 the rest will be managed by rails in Erb um so yeah this is an example of
01:09:11.640 doing that I'm going to show you more examples of that in a second markup Pro is just an API method within a component
01:09:18.640 that lets you grab the root uh of of the markup if you want the the root element
01:09:25.679 uh however so the key thing however in more practical use of glimmer when where you're going to use it in real apps uh
01:09:31.640 you would basically so for example react gives you something called react component using the react rails Plugin
01:09:37.960 or gem sorry ruby gem uh here we have a glimmer component rails helper method
01:09:43.199 that lets you embed any glimmer component within any Erb file in rails so for more serious use that's how we
01:09:50.560 would use it we uh it enables rendering any glimmer comp component in an Erb file we need to make sure to include the
01:09:56.679 glimmer Helper and application helper or any U rails helper that is being used
01:10:01.800 for a view but once you do that then you get the glimmer component method and that lets you
01:10:08.719 render things Within part of the
01:10:13.960 page so for example I can have an address container and I can render a few
01:10:19.239 things in pure HTML in Erb but then only this part I want it rendered in GL so here I can render uh an address form
01:10:26.280 component glimmer component and then you can pass it its options in Ruby from Erb
01:10:33.120 so I can pass it all the options I want to pass it from the server and then it'll render it and then it'll hydrate itself and then show up as as basically
01:10:41.120 um front end code and from that point on this address form will get managed separately from the rest of the Erb
01:10:48.159 document a as a frontend ruby uh component
01:10:54.560 so I mean we already saw a lot of components I'm just repeating the code here but we already saw it we had a top
01:10:59.920 level component that rendered the contact form in a table we had a contact form component and we have
01:11:06.760 the we had a presenter a model and the contact table component so we already saw a lot of examples of that um one
01:11:13.640 thing that I already talked about a bit which is within paragraphs the glimmer
01:11:19.000 DSL will behave differently it'll return strings instead of objects uh which will enable us to uh basically
01:11:26.120 concatenate within a a paragraph usually you want to use these tags like strong
01:11:31.280 emphasized BR for a new line etc etc like a subtext whatever uh in order to
01:11:39.040 customize the way the paragraph text is looking so to do that glimmer will
01:11:44.080 enable you to like generate text like this more conveniently in Ruby uh and I already showed you an example like I can
01:11:50.880 I I have a p and then I can open this string and then I can put these things using string interpolation that way I
01:11:57.840 can embed other tags within the P very conveniently without using the like without having to open an element the
01:12:04.199 same way as the p is open this is just string interpolation which is a lot simpler uh glimmer DSL for CSS is
01:12:11.280 another thing I already covered it gives you a rule with a selector and an expression you can have multiple
01:12:16.560 Expressions within the selector or sorry within that block and uh you can use the word rule or used r and I already showed
01:12:24.480 you an example of it and here if you have dashes that become underscores otherwise values here are
01:12:30.239 just strings and by the way like sometime so
01:12:35.840 there are a few recommendations in on HTML uh and CSS web pages about try to
01:12:43.280 use more CSS classes over um embedded
01:12:49.520 Styles uh however so sometimes if you worried about those if there's a slight
01:12:55.600 performance hit of embedding Styles directly within the document versus using Styles outside separately but
01:13:02.400 generally in my experience and a lot of like simple web pages on business apps
01:13:07.880 the the performance hit is very minimal it's not even noticeable it's like one or two milliseconds like people won't
01:13:13.719 notice so a lot of the time embedding a style tag like this is is is fast enough
01:13:18.800 in my experience uh but if you do have performance concerns you can always extract uh this CSS code into a SAS file
01:13:26.600 and manage it separately and everything you could do in SAS you could do it here too because it's just SAS is SAS and you
01:13:32.440 can this is just HTML so it'll get styled by SAS as well uh otherwise in the future there are thoughts about
01:13:39.480 perhaps supporting the idea of styled components like from react where if if I
01:13:44.600 add styles to a component it'll autogenerate a CSS class for it in the back end so that way it'll optimize
01:13:51.239 performance to avoid embedding styles in the component directly but in my experience though honestly a lot of the
01:13:57.080 time even if I do embed a style and component fast enough when I render the page but if there are concerns for it
01:14:02.280 that I am I am considering in the future doing the same exact thing of autogenerating CSS classes based on this
01:14:08.679 because this is just Ruby code in a DSL so when I interpret the DSL I can I can do whatever I want so we we could add
01:14:15.320 that behavior in the future um Ajax is is one last thing you need to know uh
01:14:21.040 but we're done really this is be glimmer so glimmer includes the opal jQuery gem which is useful for Ajax
01:14:28.360 because jQuery gives you very useful capabilities for doing ax requests and it has the same high level apis as that
01:14:35.320 uh as jQuery as jQuery except using the HTTP uh keyword so you say HTTP get you
01:14:42.040 pass it to URL and options and then you receive a response and you do work with it so it's it's all similar one thing to
01:14:48.920 note is when I receive the response body it's a pure J JavaScript object it's not
01:14:54.199 a an opal Ruby object so you have to wrap it with native to make turn it into an opal Ruby object so that's just a
01:15:01.080 small tiny thing to be aware of in the future Opel is actually exploring right
01:15:06.320 now autoc converting or Auto auto wrapping ja JavaScript objects pure JavaScript objects sorry into Ruby
01:15:12.800 objects in the future uh but uh so that that might not even be a
01:15:18.560 concern anymore in a future version of Opel but for now that's one thing to be aware of
01:15:23.800 so here's an example like I I make a call to grab sample a selected samples
01:15:28.840 code and when I receive the response I take the response body I wrap it with native to make it a ruby opal object and
01:15:35.960 then I invoke the code attribute on it so it's basically Json and the Json when
01:15:41.080 when it becomes a ruby object it has a code method and then I can grab the code and then I can set it as the selected
01:15:46.760 sample so now let's look at a at a a real app built with uh um this is like
01:15:55.040 the last thing I'm I'm showing you a real app built with this so there's an app called the sample selector that I
01:16:01.679 built and put in its own GitHub repo that is basically a Ruby on Rails app built with brail 7 uh using U uh written
01:16:09.880 in glimmer DSL for web to demonstrate glimmer DSL for web and it shows you all the samples that come with glimmer DSL
01:16:16.159 for web but also it shows you the code and it's syntax highlighted uh so it's showing you that you can build quite
01:16:22.159 like the sophisticated very quickly I built it very quickly the syntax highlighting I was able to just use a a
01:16:27.920 JavaScript library for that and I delegated all the work with it to it and the nice thing about when you're in opal
01:16:33.400 Ruby you can integrate with any JavaScript library so I just integrated with something I build this very quickly
01:16:38.480 and the code is just amazing uh but basically it lets me look into any
01:16:44.159 application like for example hello Observer and then click run and it run it runs it right away and puts it in the
01:16:51.000 browser and it gives me a back button and I can click it I go back here I go here now hello MVP that's the app that I
01:16:58.280 just showed you earlier so fill out this field so if I just put
01:17:05.840 John like this it's not going to accept it it's going to say give me an email so let's give a valid email boom it just
01:17:12.239 added it to the table um this is the hello content data
01:17:17.840 binding example that I showed you which allows you to regenerate this area with extra addresses when needed but it also
01:17:23.080 maintains the data so if I do uh John Smith here I put Chicago for example
01:17:29.199 Illinois see it maintains the data doesn't lose it when I refreshes so um
01:17:35.280 and this is demonstrating hello glimmer component but yeah let's look at the code of this so what's more interesting is the
01:17:41.440 code so by the way I'm using Gladiator which is an API uh sorry uh an IDE
01:17:46.639 built-in Ruby using glimmer DSL for S swt which is one of the glimmer libraries for desktop development
01:17:54.880 um so let's check the sample selector so this is it the sample selector is
01:18:00.840 basically this is the this entire app is this component sample selector and it
01:18:09.040 has a root container it says here run a a sample or view a samples code so this is what we see here um and
01:18:16.080 then it has code container so code container is this part so if I click on
01:18:22.000 anything here I have a code container I can scroll down in it and it shows us code with syntax highlighting in
01:18:27.719 Ruby and um samples the samples table is
01:18:32.760 this this is the samples table and the samples table
01:18:37.880 basically uh will use an each statement and and use the sample selector
01:18:43.120 presenter and loop through the samples and present them to the user
01:18:48.440 um the last sample is a special case so it needed a run and code action so I
01:18:53.520 added run and code actions for it I'm not going to get into that for now uh and here's the CSS for it it's just
01:18:59.719 using glimmer DSL for CSS so it's a very simple app and um if we look into the
01:19:05.080 presenter so yeah we're using data binding so here we're using um datab binding for detecting the class name of
01:19:12.480 an element so if I select an element the CSS class for it changes and then it gets a different color so here when I
01:19:19.080 select it it becomes blue so this is happening using this line I'm basically binding to the selected sample on the
01:19:24.840 presenter and if it's um me then I become selected if it's not then I become unselected that's it it's very
01:19:31.520 simple um and then there's an onclick action that will select the sample when I click it so when I click it it selects
01:19:37.600 it so let's look at the presenter so it has a number of
01:19:42.679 samples um I have uh sample names here okay so
01:19:48.760 this is the method that lets me select a sample and as soon as I select it it fetches the samples uh code and when I
01:19:54.840 fetch the sample code it does an Ajax call using uh jQuery uh Ajax and it does
01:20:00.480 http get it calls now this calls to a rails controller so I have a rails controller called samples controller
01:20:07.320 that is very simple uh all it does is it renders a sample and if you uh and it
01:20:13.320 uses it renders it as Json so if we look at the sample model Erb actually I have
01:20:18.520 it open already uh it's just a simple U Ruby model in r
01:20:24.040 that is initialized and it has an as Json method which gives all the fields that are needed for representing it as
01:20:29.520 Json which what to us what matters the most is code the most sophisticated part is code code will actually use uh Ruby
01:20:36.719 code in the back end to look up the actual code of the ruby gem of glimmer DS ALR web and grab the code of that
01:20:44.280 sample from it so this is pure Ruby code uh you you grab the code from it and um
01:20:50.960 it removes the license also and it returns it in the Json that's it it's it's a so nice thing is like you have
01:20:57.760 all the you know all the features of rails in the back end but then you can integrate them to all the features of
01:21:03.360 glimmer in the front end so you get something very like such a simple productive way of building the app like
01:21:09.719 the code is extremely simple the methods are generally very simple uh this method load sample will actually based on a
01:21:16.480 sample name that was selected will load the Ruby file for it from the library
01:21:22.040 from the glimmer DSL for web library on the front end though not back end on the front end um the reason why this code is
01:21:28.760 a bit tricky is because opal Ruby uh uses this technique of whenever
01:21:34.719 you use a required statement it links to a new Javascript file or sorry it compiles a new Javascript file as part
01:21:40.679 of the bundle so in order for it to know what files you need to have in this app I need to explicitly have required
01:21:47.360 statements for all of them I I so whenever you link to a file you have to have a required statement
01:21:53.400 uh so this usually this works fine when like for example here I have require
01:21:58.520 relative uh from here and I'm linking from The View I'm linking to the presenter and to another view element
01:22:04.480 which is the back anchor uh link which we actually saw it's the link that lets me uh move back this is a component as
01:22:12.480 well but basically this um so this usually works very well like whenever
01:22:17.960 there's a require or require relative Opel will add that Javascript file to the bundle however if you're doing it
01:22:23.440 dynamically Opel will not know what to load so you so that's why um one thing
01:22:29.639 to be aware of is if I'm ever linking to things dynamically I have to add them explicitly like I'm doing here but to be
01:22:36.520 honest that's not a real concern in real apps I you don't have to do that like CU When I built my app for my like for our
01:22:43.440 uh work uh web page I never had to do load dynamically uh the only reason here
01:22:49.440 I have to load things dynamically is I'm loading Ruby samples dynamically which is a very rare use case and I'm just
01:22:54.560 explaining why I have a big load State method here otherwise this method would have been very short but yeah that
01:23:00.800 that's it it's a very simple presenter and as soon as I I click on one of those
01:23:05.920 it loads this and it and it as you saw it just populates it into uh it fetches
01:23:12.000 the selected sample code and it sets it into this variable and then now this variable is actually data bind here see
01:23:19.480 we have data binding to the presenter on this attribute and this as soon as it it's updated I have a converter where it
01:23:26.560 says on read of the data invoke the highlighter which will then invoke syntax highlighting on this div and
01:23:33.120 that's what adds the syntax highlighting to the Ruby code and uh the library I'm using supports all programming languages
01:23:39.639 so if I have HTML I can highlight it differently if I want but yeah that's pretty much it it's very simple that's a
01:23:45.719 real example of how to use um glimmer DSL for web in a ruby ons application
01:23:54.040 so what is the future of glimmer DSL for web before we some wrap it up um um so I we already support glimmer
01:24:01.760 web components uh however the new HTML web component standard support has
01:24:06.960 support for slots now so I'd like to add support for web component slots to
01:24:12.639 glimmer DS alpha web as well uh there's going to be a front end routing DSL to
01:24:17.920 be able to enable the back button in the browser have browser history and friendly URLs uh so I want to add
01:24:24.760 automatic support for that it it will not necessarily be completely automatic you still have to
01:24:31.000 declare the route names and map them to components the way you would do in react for example but uh either way I need to
01:24:38.639 provide a router DSL though for that kind of like how we have a router DSL and rails in the back end I'd like to
01:24:44.520 support that on the front end with a glimmer router DSL uh support HTML web components so this is more about um I
01:24:52.440 want to be able to detect HTML web components which are which is a a standard independent of any JS library
01:24:59.320 or fun End Library and reuse them from glimmer DS alha web the benefit of that
01:25:04.800 is then I can reuse a lot of libraries as well as you can convert any react component using a library called react
01:25:10.800 to uh web components or react components I forgot what it's called but and then
01:25:16.679 reuse any react component from glimmer DS Al for web so that way if I'm if we have a an app with Legacy react code you
01:25:23.719 can reuse it in Glam DSL for web with no problem because it's simply an HTML DSL
01:25:29.239 and HTML web components are just HTML keywords they make react components
01:25:34.440 usable as HTML key uh keywords basically grb support so grb is
01:25:41.239 basically providing a glimmer a glimmer RB glimmer RB is basically providing an alternative
01:25:47.880 to Erb that is written in Ruby so instead of writing Erb codes that is part half HTML half Erb scriptlets we
01:25:55.920 write Erb as glimmer DSL codes in Ruby only so then you can add if IFL
01:26:01.600 statements in each iterators in the back end in Erb grb files sorry in place of
01:26:07.679 Erb so that's a way to help people transition slowly their backend code
01:26:12.760 view code as well from Erb to something better uh however we can go further
01:26:17.920 server components so server components is server side rendering or backend rendering of front-end web components
01:26:24.760 meaning glimmer web components as replacement of Erb so also alternatively we can forget Erb and forget even grb
01:26:32.600 and just take the the exact components that we built on the the front end and render them in the back end with
01:26:38.800 automatic hydration for JavaScript and and datab binding for JavaScript event listeners and data binding so if there
01:26:45.679 are onclick events or on change or on input or any datab binding arrows we
01:26:50.719 would Auto hydrate them as soon as the element the thing yeah the component renders in the front in so that's
01:26:56.239 something that was somebody asked me for this feature actually and ask me for the other one
01:27:02.440 grb uh someone is experimenting with glimmer DSF or we asked me for both so I'm actually looking into both of them
01:27:09.800 uh for the near future or in the future sorry I don't know when uh consider
01:27:15.560 supporting rubby wasm as an alternative to Opel so it would be ideal If eventually people can replace Opel with
01:27:22.159 Ruby WM if what's that's what they prefer and um by simply changing
01:27:29.400 updating a configuration option that's it and they can use everything the same way in Ruby wasm except maybe J jQuery
01:27:37.679 the jQuery HTTP API I think it's different than Wason but either way that's something to look into I mean I
01:27:43.239 might be able to add an adapter to have one a Jax's API as well but for now uh
01:27:49.719 I'd like to at least support the DSL itself in the same same exact way in both wasm and opal uh explore a DSL for
01:27:56.000 web canvas API so if people want to do Canvas Graphics I want to look into a ruby DSL for it uh explore how to
01:28:03.520 integrate with websockets that's that's an interesting technology to integrate with and explore how to integrate with
01:28:10.400 Hotwire turbo so Hotwire turbo is kind of orthogonal to glimmer DSL for web glimmer DSL for web is about front-end
01:28:17.480 uh codes written in Ruby hot wire turbo is more about backend generation of
01:28:22.679 uh like element replacement uh code uh without writing uh JavaScript so they're
01:28:28.679 similar but they're not the same uh it would be interesting to integrate between them when
01:28:34.560 needed uh so yeah that's it I'm done so then then in summary um Matts we started
01:28:40.760 with Matts talking about how Ruby in the browser could become the future of Ruby and how it could replace
01:28:45.960 JavaScript um we talked about why we want to use Ruby in the browser we talked about options and tradeoffs
01:28:51.719 between between JavaScript and Ruby in the browser um we went through a
01:28:57.440 full-fledged example called hello form MVP that showed the form in a table
01:29:02.639 including other features like data binding and content data binding uh we looked into the Ruby HTML DSL
01:29:10.119 Basics uh like elements arguments content and methods we looked into the MPC pattern and observers the MVP
01:29:18.560 pattern model view presenter and data binding uh like Property Data binding bidirectional or unidirectional and
01:29:24.600 content data binding um glimmer web components glimmer
01:29:31.119 paragraph for matting elements glimmer DSL for CSS Ajax with Opel jQuery
01:29:36.960 HTTP glimmer DSL for web sample selector rails app demo that's about it I have a
01:29:43.840 bunch of links here for the glimmer DSL for web project the previous talk that this is continuing which was intro to
01:29:50.400 Ruby in the browser and and a blog post announcing this uh Project's Beta release when it was released um so let's
01:29:58.760 um let's start with the Q&A period any questions who wants to go
01:30:07.000 first can go first about testing framework for R they will continue
01:30:13.000 working with that with Limer yeah so as far as I know opal Ruby does have testing Frameworks it has something
01:30:19.400 similar to rspec uh so you can that sort of testing in the front end if needed however if you're able given that
01:30:27.080 we're using MVP and MVC it lets you have very clean separation of concerns given that you can extract presenters and
01:30:33.080 models in a way where they would not be dependent on glimmer or views you can
01:30:38.119 test those presenters and models using just mini test or rspec in the back end you don't even have to write front and
01:30:43.199 test for them so that's that's a very very like beneficial thing as far as
01:30:49.199 using a a ruby in in the front end is that you can can write backend tests for them that they would work just fine if
01:30:55.560 needed but at the same time you do have front-end testing Technologies in opal Ruby any other questions um go ahead
01:31:03.520 sorry the lady over there go ahead uh with the content that I buing uh the
01:31:08.760 example the addresses like when you went from two to three addresses Etc it's
01:31:14.520 always like deleting when we go back from sorry you go back from 3 to two you
01:31:20.760 are the last one that was yes yes in that example um the the
01:31:28.400 requirements of that example were delete an address completely once the address
01:31:35.080 account diminishes however if there is a requirement to keep the third address even after diminishing the addresses so
01:31:41.840 that if I go back to three again we can redisplay the data of it that is supportable it could be supported at the
01:31:48.719 model level without the view caring about how that's implemented so that is doable if needed okay the model can keep
01:31:55.080 track of the history of the addresses that were entered and then read add it go
01:32:02.159 ahead the couple names well
01:32:07.960 was uh like generating uh metal names to be G from other components MH uh I was
01:32:16.520 wondering if the components uh class names and uh name spacing with modules yes yes
01:32:24.639 they do so if if you're concerned about for example I built my own address form and then I imported a library that has
01:32:31.239 address form um I would assume that the library names SPAC their address form so
01:32:37.280 if they Nam namespaced it for example leop address form then when I use it I
01:32:42.480 can either use it use it with the short name which is just address form or you can use it with a fully namespaced name
01:32:48.400 which is um um it start starts with the module that contains the address form so
01:32:53.840 if it's leop containing address form then you can say leop Dore addressor
01:33:00.840 form uh so glimmer already automatically supports that to handle to prevent
01:33:06.480 namespace collisions in components so that way for example 15 libraries can Implement address form if they want and
01:33:13.239 each one would have a namespace differently so the consumer if they had only one of them they can use the short
01:33:18.480 name just address uncore form if they had two or three of of them they and they want to select one only that styled
01:33:24.960 a special way then they can use the full fully namespaced name of the component
01:33:31.800 yes any other questions okay thank you everybody for
01:33:37.440 uh hanging out with me for this long it went way over uh the time that was
01:33:50.560 much what
Explore all talks recorded at Montreal.rb Meetup
+6