<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andy Maleh</title>
    <description>The latest articles on DEV Community by Andy Maleh (@andyobtiva).</description>
    <link>https://dev.to/andyobtiva</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F412144%2F29cbb952-50ac-4671-84cc-fc190f15887c.jpeg</url>
      <title>DEV Community: Andy Maleh</title>
      <link>https://dev.to/andyobtiva</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andyobtiva"/>
    <language>en</language>
    <item>
      <title>Ruby Memes 2026-06-12 The "Cool" Reactionary</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Fri, 12 Jun 2026 22:04:15 +0000</pubDate>
      <link>https://dev.to/andyobtiva/ruby-memes-2026-06-12-the-cool-reactionary-5hge</link>
      <guid>https://dev.to/andyobtiva/ruby-memes-2026-06-12-the-cool-reactionary-5hge</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F956qky2zseys4x4msvty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F956qky2zseys4x4msvty.png" alt=" " width="640" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Shareable blog post edition:&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2026/06/ruby-memes-2026-06-12-cool-reactionary.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2026/06/ruby-memes-2026-06-12-cool-reactionary.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>frontend</category>
      <category>opal</category>
    </item>
    <item>
      <title>Andy's Laws of AI in Software Engineering</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Tue, 09 Jun 2026 18:32:14 +0000</pubDate>
      <link>https://dev.to/andyobtiva/andys-laws-of-ai-in-software-engineering-2f23</link>
      <guid>https://dev.to/andyobtiva/andys-laws-of-ai-in-software-engineering-2f23</guid>
      <description>&lt;p&gt;Shareable blog post edition:&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2026/06/andys-laws-of-ai-in-software-engineering.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2026/06/andys-laws-of-ai-in-software-engineering.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Law #1: "The more Software Developers use AI, the more valuable Software Engineers who do not use AI become."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Software Engineers who are masters at delivering Software without using AI will actually have increased job security the more Software Developers in the worldwide Software Development community rely on AI to deliver Software without having true mastery over Software Engineering.&lt;/p&gt;

&lt;p&gt;As more Software Developers become fully dependent on AI to build Software without truly understanding how AI gets work done, Software Engineers who do understand what is going on under the hood will dwindle and become more valuable than ever. In other words, they will have a competitive advantage over Software Developers who can only deliver Software features with AI as well as Software Developers who have not mastered Software Engineering.&lt;/p&gt;

&lt;p&gt;Also, there will always be a need for Software Engineers who can maintain the Software of AI itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Law #2: "Software Developers benefit from AI in direct proportion to how weak they are in Software Engineering"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The weaker Software Developers are at Software Engineering the more they benefit from AI. After all, AI learns from Master Software Engineers and then applies its learnings in code generation done for lower-level Software Developers who lack mastery in Software Engineering. So, users of AI simply place themselves lower in the expertise hierarchy to be on the receiving end of what Master Software Engineers feed AI with their code. This explains why many experts like Linus Torvalds do not find AI very useful while devs who have zero degrees and qualifications feel like they get a lot from AI.&lt;/p&gt;

&lt;p&gt;A beneficial thing to learn from this law is that it is more valuable for a Software Developer to hone in their Software Engineering skills (including the completion of university degrees) than to hone in their AI usage skills because if they achieve mastery over Software Engineering, they would cease to need AI to do their job well for customers. In other words, if a Software Developer feels like they benefit from AI even a little bit, then that means they have some unhandled weakness and are lacking some skills in Software Engineering they could be improving instead. Using AI after all takes away from the recommended 10,000 hours of Software Engineering practice to achieve mastery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Law #3: "AI's speed is negated when it produces Software features faster than customers can test and learn."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Code generation is not the bottleneck when customers still have to test every Software feature at a human pace to provide real human feedback before iterating further for future improvement. So, given that customers still need to provide human feedback with non-AI testing, that negates the need for Software Engineers to produce code faster, rendering AI's speed benefits moot. Producing code with Lean Software Processes is fast enough for that need.&lt;/p&gt;

&lt;p&gt;Furthermore, Software has a limit to acceptable complexity by customers in relation to how many features it contains. So, if customers get too many features, they get overwhelmed, and that also eliminates the benefits of AI's speed. In other words, customers prefer quality over quantity.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>softwareprocess</category>
    </item>
    <item>
      <title>RubyConf has joined RailsConf &amp; RailsWorld as another exclusive discriminatory unexcellent conference</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Fri, 05 Jun 2026 23:18:46 +0000</pubDate>
      <link>https://dev.to/andyobtiva/rubyconf-has-joined-railsconf-railsworld-as-another-exclusive-discriminatory-unexcellent-3h65</link>
      <guid>https://dev.to/andyobtiva/rubyconf-has-joined-railsconf-railsworld-as-another-exclusive-discriminatory-unexcellent-3h65</guid>
      <description>&lt;p&gt;(Originally published as this blog post: &lt;a href="https://andymaleh.blogspot.com/2026/06/rubyconf-has-joined-railsconfrailsworld.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2026/06/rubyconf-has-joined-railsconfrailsworld.html&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;RubyConf has joined RailsConf &amp;amp; RailsWorld as another exclusive discriminatory unexcellent conference by discriminating against any speakers who submit talks that cover Frontend Ruby technologies or dethrone React/JavaScript in any way. In 2025, &lt;a href="https://andymaleh.blogspot.com/2025/01/glimmer-dsl-for-web-wins-in-fukuoka.html" rel="noopener noreferrer"&gt;I won an award for a highly innovative and outside-the-box Ruby open-source project at an international Japanese tech competition&lt;/a&gt; that Matz, the creator of Ruby himself, presided on in addition to other judges. My project really impressed Matz, who is the reason for all the Ruby-related conferences existing in the first place, but in spite of that, both RailsConf and RailsWorld rejected my talk about my &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web" rel="noopener noreferrer"&gt;award-winning open-source project&lt;/a&gt; in 2025 despite the Ruby on Rails community sorely needing a Frontend Ruby solution that would fill a gap not handled by Hotwire; that is true Frontend Development in Ruby (to build frontend-local apps like a UML Diagrammer for example). Given that I am the most qualified person to talk about Frontend Development in Ruby on Rails using real Ruby in the Browser, and no other Frontend technologies rival my project in either productivity or simplicity/maintainability, the rejections came across as discrimination/exclusion and mediocrity/closed-mindedness/lack of appreciation for excellence. After all, if you reject an open-source project that won an award by Matz, your action is sending everyone the discouraging message that it doesn't matter how hard Software Engineers work to produce a unique innovation; they will stil be rejected because of discrimination and lack of appreciation for excellence if it comes from outside the core group behind Rails and some of their sponsors/friends. The reason this is also discrimination is because I was not rejected due to being disqualified while the project I want to talk about provides great value to the Ruby on Rails community. It saves Ruby on Rails Software Engineers who use JavaScript libraries like React.js/Angular/Vue/Svelte 6 months of Frontend work every year. I don't know many talks at RubyConf in general that can offer the same benefit. And, I am sure that nobody is as qualified as me on the subject of Ruby Frontend Development, plus no one at either RailsConf or RailsWorld has won a similar award to mine at an international tech competition that was judged by Matz (and &lt;a href="https://andymaleh.blogspot.com/2022/02/glimmer-dsl-for-libui-wins-fukuoka-ruby.html" rel="noopener noreferrer"&gt;I have done it one other time&lt;/a&gt; previously too in fact). &lt;/p&gt;

&lt;p&gt;Fortunately, this year, my &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web" rel="noopener noreferrer"&gt;award-winning open-source project&lt;/a&gt; got accepted at RubyConf Austria 2026 (&lt;a href="https://andymaleh.blogspot.com/2026/06/rubyconf-austria-2026-frontend-ruby-on.html" rel="noopener noreferrer"&gt;30-minute talk&lt;/a&gt;) and wroclove.rb 2026 (&lt;a href="https://andymaleh.blogspot.com/2026/04/exercises-for-wrocloverb-2026-ruby.html" rel="noopener noreferrer"&gt;3-hour workshop&lt;/a&gt;). Those conferences are much better run than RailsConf and RailsWorld in welcoming innovation and being inclusive! wroclove.rb 2026 literally says on their website that they "want to confront ideas", in contrast to RailsConf and RailsWorld running away from ideas that don't come from the Rails core devs and some of their sponsors/friends (a form of discrimination). RubyConf Austria &amp;amp; wroclove.rb don't discriminate against Frontend Ruby projects and aren't offended by a talk that dethrones React/JavaScript, especially if already approved by Matz, the creator of Ruby. They welcome the excellence and hard work that went into creating my award-winning open-source Ruby project and winning an award from Matz, the creator of Ruby. In other words, they encourage the Ruby community to be excellent and follow my example in innovation and thinking outside the box. In fact, I met &lt;a href="https://chadfowler.com/" rel="noopener noreferrer"&gt;Chad Fowler&lt;/a&gt; at RubyConf Austria 2026, and he attended my talk, then told me "good job" afterwards. For those who don't know, &lt;a href="https://chadfowler.com/" rel="noopener noreferrer"&gt;Chad Fowler&lt;/a&gt; founded RubyConf back in 2001. &lt;/p&gt;

&lt;p&gt;So, I submitted my &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web" rel="noopener noreferrer"&gt;award-winning open-source project&lt;/a&gt;'s talk to RubyConf in 2026 thinking they might be less averse to Frontend Ruby, especially if the speaker won an award from Matz, given RubyConf is typically more open-minded about Ruby innovations outside of core Rails. Well, I got rejected despite being accepted by Matz, the creator of the language that conference was founded upon. I asked by email for the reasons for the rejection and for feedback to help improve myself in case they want me to do better before getting accepted (though to be frank, I won an award from the creator of Ruby himself, and there isn't anything that can top that). They never responded. &lt;/p&gt;

&lt;p&gt;I want to clarify that I have supported RubyConf in the past by giving talks/workshops at it and by donating my speaker stipends/hotel-pay (over $1000 or $2000 for all the conferences I spoke at) back to RubyCentral for the benefit of the Ruby community as a whole with everyone in it. So, it's not much to ask for a response as to why I encountered behavior that came across as discrimination when I have gone above and beyond in the past in supporting RubyConf and RubyCentral.&lt;/p&gt;

&lt;p&gt;Eventually, I remembered that I have 2 RubyConf/RubyCentral people as LinkedIn connections, Jason Swett and Freedom Dumlao, so I contacted them asking the same question. I also pointed out to them that I am a former RubyConf speaker who donated his speaking stipends from the last 3 RubyConfs back to RubyCentral for the benefit of the Ruby community at large (that's over $1000). So, being treated with respect and non-discrimination is the least I could expect from RubyCentral.&lt;/p&gt;

&lt;p&gt;Jason Swett chose the coward's plea and just never responded, which is how true discriminators handle discrimination when it's raised to them. The reason this incriminates him 100% is because if he truly wasn't involved in discrimination, he would have at least responded by saying he sympathizes with me perceiving discrimination and by indicating he is shocked that a project that won an award from Matz (when many other RubyConf talk projects didn't win any awards from Matz) got rejected at RubyConf. Honestly, Jason reminds me of employees that my employers fired in the past. Lack of presence and visibility is usually the sign of an unreliable employee who is never there for others. So, I advise against hiring Jason Swett (unless he responds to me and clears up my experienced discrimination).&lt;/p&gt;

&lt;p&gt;Freedom Dumlao didn't respond to my first message, but at least responded to my 2nd follow-up message. He gets some points for that. Otherwise, his response was very weird and defensive. He claimed with a very unfriendly tone that I didn't know him even though him and I met at RubyConf 2024 and sat at the same eating table multiple times while having conversations that eventually led to connecting on LinkedIn. In fact, it sounded like he was trying to get out of responsibility by claiming I did not know him enough (a very unnice unfriendly thing to say from a Rubyist) even though the world is a meritocracy anyways, meaning people are known through their actions in day to day interactions, whether ethical or unethical. The way he said that came across as immature and irresponsible, not the way someone at RubyCentral should be talking. After all, a responsible person would have not focused on that, yet focused on my experience of discrimination and how strange it is that a project that was approved by Matz in a very difficult international competition and got a "good job" remark from Chad Fowler (the founder of RubyConf) got rejected at RubyConf, which would indicate RubyConf's staff are unqualified and do not appreciate excellence, in addition to having discriminatory biases, like the bias against Frontend Ruby and biases for React/JavaScript that cause offense if they are dethroned (shameful at a Ruby conference that is supposed to make Software Engineers feel safe about loving Ruby more than other languages). None of them have won similar awards from Matz, most likely in fact. A person in Freedom's position should have been sincerely concerned and should have noticed the problem and then promised a solution without making any excuses, just like how excellent organizations behave. Given that he didn't respond that way, even if I didn't know him, his reaction told me and everyone everything about him that we need to know about who he really is. He showed that he's part of the problem not the solution.&lt;/p&gt;

&lt;p&gt;Regarding my donations to RubyCentral that exceed $1000, Freedom tried to deny the value of my donation by saying he donated more to RubyCentral, believe it or not! What a creepy disrespectful way to talk to someone who gave you money for free without being required to. Invalidating a donation is NOT a way to encourage people to continue donating, yet sends the message that donations are discouraged because in the end, they won't matter anyways as "someone else donated more than you". That was the most unhinged unprofessional encounter I've had from someone who is supposed to be a professional! Honestly, it doesn't matter how much he donated. My donations still have the same value in helping RubyCentral and the Ruby community regardless. Other people's donations definitely don't invalidate mine. &lt;/p&gt;

&lt;p&gt;Freedom also proceeded to claim that there was "no discrimination" because all their talks are reviewed anonymously. EXCEPT, my talk was NOT reviewed anonymously, because it mentions a public project on GitHub (which shows the author as soon as one visits it) and a public award (with the winner's name) that the project won from Matz at a public competition. &lt;/p&gt;

&lt;p&gt;I responded to inform him that my proposal submission wasn't anonymous as that was impossible with the talk being about a GitHub project and having won an award. And, I informed him that my donation is definitely NOT invalidated because he donated more. Freedom then chose the coward's plea and didn't respond. I advise against hiring Freedom Dumlao for any jobs or services as a result. He's the kind of selfish irresponsible excuse maker who is only about protecting his own hide while not caring about encouraging and maintaining excellence in a community, nor respecting people who donate to the community without being required to.&lt;/p&gt;

&lt;p&gt;You see what i'm dealing with here!? Total trash! These are the kind of people running RubyCentral today! No matter it encountered issues last year with the Mike Perham vs DHH debacle, in addition to stopping RailsConf. The Ruby community is being run by total clowns who are discriminatory, unethical, and unprofessional!&lt;/p&gt;

&lt;p&gt;I have ZERO interest in attending RubyConf 2026 as a result. After all, if they rejected a talk by one of the best open-source Ruby projects to come out in 2025 as to win an award by Matz, the creator of Ruby himself, then they probably rejected many other project talks that are top equality because of the lack of qualification of RubyConf staff in 2026. For all we care, we got the dumbest, but most popular, talks in RubyConf 2026, but smart Software Engineers know that popularity is NOT quality. After all, PHP/WordPress is more popular than Rails, but definitely inferior in productivity and maintainability, which is why Ruby on Rails devs don't use those technologies in general. &lt;/p&gt;

&lt;p&gt;In conclusion, RubyConf in 2026 has become an exclusive discriminatory unexcellent conference, which is where people go to become dumber and/or meaner. &lt;/p&gt;

&lt;p&gt;I have covered the topic of &lt;a href="https://andymaleh.blogspot.com/2024/12/how-to-spot-covert-discrimination-in.html" rel="noopener noreferrer"&gt;covert discrimination in the Ruby community&lt;/a&gt; before. What I encountered at the hands of the RubyConf folks is classic covert discrimination. Spread the word to help stop discrimination and unexcellence in the Ruby community! In the meantime, I'll make sure to only attend and speak at Ruby conferences that don't have unprofessional unexcellent discriminatory staff.&lt;/p&gt;

&lt;p&gt;P.S. To prove that I'm reasonable and on the right side of this, I will acknowledge that nobody is perfect and everyone makes mistakes. What distinguishes good people from bad people though is that good people will admit their errors and apologize for their mistakes when they are pointed out to them whereas bad people will act aloof and commit more discrimination/exclusion by ignoring you when that happens. If any of the problematic people mentioned in the article change their mind and decide to respond like real men (not by hiding like cowards) to resolve my concerns about discrimination/exclusion/unexcellence for the benefit of the cheated Ruby community that missed out on all the Matz-loved value provided by an award winning open-source Ruby project that impressed Matz, then I'll delete this blog post. &lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>conference</category>
      <category>discrimination</category>
    </item>
    <item>
      <title>Presentation Slides for RubyConf Austria 2026 Talk "Frontend Ruby on Rails with Glimmer DSL for Web"</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Tue, 02 Jun 2026 21:34:17 +0000</pubDate>
      <link>https://dev.to/andyobtiva/presentation-slides-for-rubyconf-austria-2026-talk-frontend-ruby-on-rails-with-glimmer-dsl-for-web-2hi</link>
      <guid>https://dev.to/andyobtiva/presentation-slides-for-rubyconf-austria-2026-talk-frontend-ruby-on-rails-with-glimmer-dsl-for-web-2hi</guid>
      <description>&lt;p&gt;My talk &lt;a href="https://bit.ly/glimmer-rubyconf-at-2026" rel="noopener noreferrer"&gt;“Frontend Ruby on Rails with Glimmer DSL for Web”&lt;/a&gt; went well at &lt;a href="https://rubyconf.at/" rel="noopener noreferrer"&gt;RubyConf Austria 2026&lt;/a&gt;. Especially given that after the talk, &lt;a href="https://chadfowler.com/" rel="noopener noreferrer"&gt;Chad Fowler&lt;/a&gt; (the starter of RubyConf and famous book author of &lt;a href="https://www.amazon.ca/Passionate-Programmer-Creating-Remarkable-Development/dp/1934356344" rel="noopener noreferrer"&gt;The Passionate Programmer&lt;/a&gt;, among other books) told me “good job”, and &lt;a href="https://obiefernandez.com/" rel="noopener noreferrer"&gt;Obie Fernandez&lt;/a&gt; (a famous entrepreneur and book author of &lt;a href="https://leanpub.com/therails8way" rel="noopener noreferrer"&gt;The Rails Way&lt;/a&gt;, among other books) told me he will try Glimmer DSL for Web because he doesn’t like React.js.&lt;/p&gt;

&lt;p&gt;Presentation Slides Direct Original Long Link:&lt;br&gt;
&lt;a href="https://docs.google.com/presentation/d/e/2PACX-1vQ9oBnZpzK_eicVLGSqDmVzhsXsblONEKepnw5_xGHGXTM52JSjaS_ObYUJbx-zkb1M2ul9N2A2MnvU/pub?start=false&amp;amp;loop=false&amp;amp;delayms=60000&amp;amp;slide=id.g140fe579a5a_0_0" rel="noopener noreferrer"&gt;https://docs.google.com/presentation/d/e/2PACX-1vQ9oBnZpzK_eicVLGSqDmVzhsXsblONEKepnw5_xGHGXTM52JSjaS_ObYUJbx-zkb1M2ul9N2A2MnvU/pub?start=false&amp;amp;loop=false&amp;amp;delayms=60000&amp;amp;slide=id.g140fe579a5a_0_0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Glimmer DSL for Web GitHub:&lt;br&gt;
&lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web" rel="noopener noreferrer"&gt;https://github.com/AndyObtiva/glimmer-dsl-web&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I ran a poll at the beginning of my talk, and everyone agreed that they love Ruby and that Ruby is superior to JavaScript, plus the majority indicated that they’d like to write less JavaScript and more Ruby during their Rails web development work. Several attendees told me my talk was great after the talk. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.headius.com/" rel="noopener noreferrer"&gt;Charles Nutter&lt;/a&gt; had me help him with his &lt;a href="https://www.jruby.org/" rel="noopener noreferrer"&gt;JRuby&lt;/a&gt; workshop afterwards by showcasing my other Glimmer project, &lt;a href="https://github.com/andyobtiva/glimmer-dsl-swt" rel="noopener noreferrer"&gt;Glimmer DSL for SWT&lt;/a&gt;, which runs on JRuby. In about 1 minute, I scaffolded a Hello World desktop app from scratch and then packaged it as a native executable on the Mac. Attendees were impressed. So, I’ve participated in presenting 2 events at this conference. &lt;/p&gt;

&lt;p&gt;I am very grateful for having such a great experience at &lt;a href="https://rubyconf.at/" rel="noopener noreferrer"&gt;RubyConf Austria 2026&lt;/a&gt; overall, especially given that it uniquely included several classical/neoclassical/jazz concerts in between talks that entertained us and relaxed us. &lt;a href="https://chadfowler.com/" rel="noopener noreferrer"&gt;Chad Fowler&lt;/a&gt; concluded the conference with a beautiful Jazz piano and sax performance. Shout out to Hans Schnedlitz, Muhamed Isabegovic, and Zuzanna Kusznir (plus everyone who helped out) for organizing and hosting such a special &lt;a href="https://www.ruby-lang.org/en/" rel="noopener noreferrer"&gt;Ruby&lt;/a&gt; conference!!!&lt;/p&gt;

&lt;p&gt;Original blog post version:&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2026/06/rubyconf-austria-2026-frontend-ruby-on.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2026/06/rubyconf-austria-2026-frontend-ruby-on.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>frontend</category>
      <category>glimmer</category>
    </item>
    <item>
      <title>I published a GitHub repo for the exercises of the wroclove.rb 2026 workshop "Building Rails SPAs in Frontend Ruby with Glimmer DSL for Web". And, Glimmer DSL for Web now has official Rails 8 setup instructions... https://bit.ly/4trJOck</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Sat, 25 Apr 2026 00:53:13 +0000</pubDate>
      <link>https://dev.to/andyobtiva/i-published-a-github-repo-for-the-exercises-of-the-wrocloverb-2026-workshop-building-rails-spas-4k1d</link>
      <guid>https://dev.to/andyobtiva/i-published-a-github-repo-for-the-exercises-of-the-wrocloverb-2026-workshop-building-rails-spas-4k1d</guid>
      <description>&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://andymaleh.blogspot.com/2026/04/exercises-for-wrocloverb-2026-ruby.html" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fblogger_img_proxy%2FAEn0k_u54aWqbeFvwU3C7Rq2eaZbLXx3v48x2-oIoV_K_k-FqaW8HpE_gCA0uGptiIviRcDusl1uRz8BYTPYcz6JOS7EjAOMVkIve3rRLPPZSJlIoWdSRSyYgTvi53bjNgeVHgCTpPN6GvEYyFQB7AutbySNafvgLGiCS8ysGx5e6T34m2zk7T989jCWeI4NW8USdg5tlzU%3Dw1200-h630-p-k-no-nu" height="630" class="m-0" width="1200"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://andymaleh.blogspot.com/2026/04/exercises-for-wrocloverb-2026-ruby.html" rel="noopener noreferrer" class="c-link"&gt;
            Code Master Blog: Exercises for the wroclove.rb 2026 Ruby conference workshop "Building Rails SPAs in Frontend Ruby with Glimmer DSL for Web"
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandymaleh.blogspot.com%2Ffavicon.ico" width="16" height="16"&gt;
          andymaleh.blogspot.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>rails</category>
      <category>ruby</category>
      <category>showdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>2025 Reminder That DHH Is a Total Idiot!</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Fri, 28 Mar 2025 16:42:32 +0000</pubDate>
      <link>https://dev.to/andyobtiva/2025-reminder-that-dhh-is-a-total-idiot-44h7</link>
      <guid>https://dev.to/andyobtiva/2025-reminder-that-dhh-is-a-total-idiot-44h7</guid>
      <description>&lt;p&gt;Just a reminder that DHH is a total idiot for not adding any Frontend Ruby tech to the Rails stack in recent years. For the last 10 years, he's pretended to be "forward thinking" and "innovative", but has been closed-minded and standing in the way of progress. He is not what he used to be when he was open-minded in the minded-2000s and helped merge Merb with Rails. Nowadays, he is clearly biased towards JavaScript against Ruby to the detriment of the Ruby community. He claims he is "embracing" JavaScript for "pragmatic reasons", which might sound good on paper and might be something I'd normally agree with, but in fact is hurting the Ruby community significantly as illustrated by the attached JS code examples that many Ruby on Rails devs write nowadays as a result of DHH's closed-mindedness and stupidity. His claim for embracing JavaScript would only be true if there weren't huge differences between JavaScript and Ruby, alas there are enormous differences between the two languages. As such, DHH is an idiot and will always be called idiot unless he corrects his ways and apologizes for destroying the Ruby on Rails community by enabling devs to write code like the attached code in the last 10 years. The blood of such crappy code is on DHH's hands! Only bigger idiots would support DHH's idiotic position. They're all enemies of progress and innovation in the Ruby on Rails community. We all know Hotwire isn't enough, and the Stimulus bit is the part that many devs replace with React.js eventually or from the get-go because it doesn't solve everything effectively and conveniently. By the way, I do not necessarily propose that everyone needs Frontend Ruby as Hotwire could be sufficient for more basic Rails projects, but 100% of devs who use JS libraries like React/Angular/Ember/Vue/Svelte have zero excuses not using Frontend Ruby instead to cut their work by half with much better possibilities facilitated only by the Ruby programming language. The fact that DHH doesn't get that demonstrates how much out of depth and out of touch he's become in Ruby over the last 10 years.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib0utiyl8vikln8q7y4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib0utiyl8vikln8q7y4j.png" alt="Image description" width="800" height="1004"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhvllprym2820vspy6xe.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhvllprym2820vspy6xe.jpeg" alt="Image description" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>JavaScript is a disease! Ruby is the cure!</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Fri, 11 Oct 2024 20:05:58 +0000</pubDate>
      <link>https://dev.to/andyobtiva/javascript-is-a-disease-ruby-is-the-cure-4c3</link>
      <guid>https://dev.to/andyobtiva/javascript-is-a-disease-ruby-is-the-cure-4c3</guid>
      <description>&lt;p&gt;In a recent Ruby meetup, I called JavaScript a disease! It is true! Especially, when comparing JavaScript code to much better, more elegant, and more readable Ruby code! JavaScript looks like ugly smelly mold by comparison. Once you see it, you can never unsee it! That's why I wouldn't touch JavaScript with a ten foot pole if I can help it in 2024. I would use Frontend Ruby instead (e.g. Opal Ruby, WASM, or Ruby2JS). Opal Ruby can usually be setup in about 10 minutes in a Rails app (&lt;a href="https://github.com/opal/opal-rails" rel="noopener noreferrer"&gt;https://github.com/opal/opal-rails&lt;/a&gt;), and it yields smaller downloadables than WASM. I am not sure why anyone in 2024 would go through the Hell of JavaScript in their otherwise pristine Ruby on Rails codebase instead of actually entering Heaven by using Frontend Ruby! Opal Ruby has won a &lt;a href="https://www.digitalfukuoka.jp/topics/228?locale=ja" rel="noopener noreferrer"&gt;Fukuoka Ruby 2023 Award&lt;/a&gt; and supports Ruby 3.1 with the ability to use any pure Ruby gems in the Frontend by simply including them in Gemfile. That removes the need for a complicated JavaScript bundling beast like Webpack. In the past, I might have advocated for still using JavaScript in smaller apps, but the barrier of integrating modern Ruby into the Frontend of Rails applications has become so non-existent with Opal, there are no more excuses for using JavaScript in a Ruby on Rails codebase. &lt;/p&gt;

&lt;p&gt;Yahuda Katz mentioned in his keynote speech at RailsConf 2014 (&lt;a href="https://youtu.be/9naDS3r4MbY?t=1195" rel="noopener noreferrer"&gt;https://youtu.be/9naDS3r4MbY?t=1195&lt;/a&gt;), which borrowed ideas from Steve Jobs, that by continuously building more floors for the lower levels of a building in the form of a framework and a community of open-source projects, we enable developers to start development at higher and higher levels than they would have been able to otherwise, thus helping them leapfrog earlier ways of development in ever increasing productivity! In 2024, Frontend Ruby (e.g. Opal) is the next floor level that enables Ruby Software Engineers to start at a higher level of development with much higher productivity and maintainability. I strongly believe that anyone who is not using Frontend Ruby in 2024 is at least half as productive as those who are using Frontend Ruby in their Rails development, regardless of whatever framework they are using. I don't care if someone is enamored by some "cool JavaScript framework xyz"; try to implement that framework in Ruby, and IT WILL BE EVER COOLER AND BETTER IN RUBY! Or, in certain instances, you will discover that Ruby is so much simpler than JavaScript, YOU DO NOT EVEN NEED the "cool" JavaScript frameworks as they are UNCOOL IN RUBYLAND! Glimmer DSL for Web is one Frontend Ruby Framework example that demonstrates the unique simplicity/readability of Ruby that is unmatched by cryptic/too-clever JavaScript code: &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web" rel="noopener noreferrer"&gt;https://github.com/AndyObtiva/glimmer-dsl-web&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JavaScript is a disease! Ruby is the cure! Don't be part of the problem by using JavaScript in Ruby on Rails codebases! Be part of the solution by using the language we all love, Ruby, isomorphically in Ruby on Rails applications in 2024 and beyond!&lt;/p&gt;

&lt;p&gt;Blog post version for sharing:&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2024/10/javascript-is-disease-ruby-is-cure.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2024/10/javascript-is-disease-ruby-is-cure.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Lack of Support and Participation in the Software Engineering Community Violates The Software Engineering Code of Ethics</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Mon, 16 Sep 2024 20:06:14 +0000</pubDate>
      <link>https://dev.to/andyobtiva/lack-of-support-and-participation-in-the-software-engineering-community-violates-the-software-engineering-code-of-ethics-2f1p</link>
      <guid>https://dev.to/andyobtiva/lack-of-support-and-participation-in-the-software-engineering-community-violates-the-software-engineering-code-of-ethics-2f1p</guid>
      <description>&lt;p&gt;Some Software Engineers mention "not being interested" as an excuse not to help someone with something that could benefit customers or the Software Engineering community at large when the real reason is in fact covert discrimination against that person and lack of effort to treat them as an equal and equally respected member of their community. Know that Software Engineers have to abide by the Software Engineering Code of Ethics:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.computer.org/education/code-of-ethics" rel="noopener noreferrer"&gt;https://www.computer.org/education/code-of-ethics&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And, it includes the statements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Software engineers shall act consistently with the public interest."&lt;/li&gt;
&lt;li&gt;"Software engineers shall be fair to and supportive of their colleagues."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, if someone gives you an excuse of "not being interested" to avoid helping you out with a public interest matter out of discrimination against you, know that they have conducted themselves in an unethical manner and remind them of what they signed up for when they became Software Engineers, whether implicitly or explicitly.&lt;/p&gt;

&lt;p&gt;This even extends to matters like Software Engineers not wanting to check out certain technologies/libraries that could greatly help the public interest just out of discrimination against the technology/library creators. It also covers matters of Software Engineers not wanting to learn and improve certain skills through frequent attendance of local user groups that can improve the practice of their profession.&lt;/p&gt;

&lt;p&gt;After all, that is covered by the statement:&lt;/p&gt;

&lt;p&gt;"Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession."&lt;/p&gt;

&lt;p&gt;I am including the short version of the Software Engineering Code of Ethics below for your convenience:&lt;/p&gt;

&lt;p&gt;Software engineers shall commit themselves to making the analysis, specification, design, development, testing and maintenance of software a beneficial and respected profession. In accordance with their commitment to the health, safety and welfare of the public, software engineers shall adhere to the following Eight Principles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;PUBLIC – Software engineers shall act consistently with the public interest.&lt;/li&gt;
&lt;li&gt;CLIENT AND EMPLOYER – Software engineers shall act in a manner that is in the best interests of their client and employer consistent with the public interest.&lt;/li&gt;
&lt;li&gt;PRODUCT – Software engineers shall ensure that their products and related modifications meet the highest professional standards possible.&lt;/li&gt;
&lt;li&gt;JUDGMENT – Software engineers shall maintain integrity and independence in their professional judgment.&lt;/li&gt;
&lt;li&gt;MANAGEMENT – Software engineering managers and leaders shall subscribe to and promote an ethical approach to the management of software development and maintenance.&lt;/li&gt;
&lt;li&gt;PROFESSION – Software engineers shall advance the integrity and reputation of the profession consistent with the public interest.&lt;/li&gt;
&lt;li&gt;COLLEAGUES – Software engineers shall be fair to and supportive of their colleagues.&lt;/li&gt;
&lt;li&gt;SELF – Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Blog post version for sharing, titled "Lack of Support and Participation in the Software Engineering Community Violates The Software Engineering Code of Ethics":&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2024/09/lack-of-support-and-participation-in.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2024/09/lack-of-support-and-participation-in.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>community</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>10x Developer Puzzle, Solved!!!</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Tue, 03 Sep 2024 19:26:51 +0000</pubDate>
      <link>https://dev.to/andyobtiva/10x-developer-puzzle-solved-3ceh</link>
      <guid>https://dev.to/andyobtiva/10x-developer-puzzle-solved-3ceh</guid>
      <description>&lt;p&gt;Here is a thought! The mythical 10x Developer is simply a developer that eliminates 9/10 of unnecessary over-engineered code, and then writes the remaining 1/10 of the code needed at the productivity rate of a 1x Developer!&lt;/p&gt;

&lt;p&gt;Such a developer might come across as a 10x Developer to others when in fact, all they are is a 1x Developer that knows how to cut the fat of over-engineering out and avoid unnecessary overhyped libraries/languages/technologies to eliminate 9/10 of development waste and only do 1/10 of the work otherwise done. &lt;/p&gt;

&lt;p&gt;I believe I have just solved the 10x Developer puzzle for once and for all! The 10x Developer mystery has been demystified for good!!&lt;/p&gt;

&lt;p&gt;Originally posted at the Code Master blog:&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2024/09/10x-developer-puzzle-solved.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2024/09/10x-developer-puzzle-solved.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Glimmer DSL for Web Ruby Integration with JavaScript Libraries</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Fri, 17 May 2024 21:28:03 +0000</pubDate>
      <link>https://dev.to/andyobtiva/glimmer-dsl-for-web-ruby-integration-with-javascript-libraries-1b32</link>
      <guid>https://dev.to/andyobtiva/glimmer-dsl-for-web-ruby-integration-with-javascript-libraries-1b32</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web"&gt;Glimmer DSL for Web&lt;/a&gt; is a &lt;a href="https://www.youtube.com/watch?v=4AdcfbI6A4c"&gt;Ruby-in-the-Browser&lt;/a&gt; Web Frontend Framework that enables Rubyists to finally have Ruby productivity and happiness in the Frontend via a simpler, more intuitive, more straightforward, and more productive library than all JavaScript libraries like React, Angular, Ember, Vue, Svelte, etc.... &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web"&gt;Glimmer DSL for Web&lt;/a&gt;'s Rails sample app "&lt;a href="https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app"&gt;Sample Selector&lt;/a&gt;" has been upgraded with Code Syntax Highlighting by integrating with &lt;a href="https://highlightjs.org/"&gt;highlight.js&lt;/a&gt;. It demonstrates how to integrate with JavaScript libraries, how to build Glimmer Web Components in the Frontend, and how to make HTTP calls from a Ruby Frontend to a Ruby Backend in a Rails application, among other things.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3_THfJR7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/raw/master/sample-glimmer-dsl-web-rails7-app.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3_THfJR7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/raw/master/sample-glimmer-dsl-web-rails7-app.gif" alt="Sample Selector" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app"&gt;Sample Selector&lt;/a&gt; Rails app enables users to list all samples that ship with the glimmer-dsl-web Ruby gem, show each sample's entry point code, and run the sample in the browser. &lt;/p&gt;

&lt;p&gt;Here is a breakdown of the code:&lt;/p&gt;

&lt;p&gt;The Rails layout includes links to the highlight.js javascript CDN URLs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;SampleGlimmerDslOpalRails7App&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width,initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;csrf_meta_tags&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;csp_meta_tag&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/ruby.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;stylesheet_link_tag&lt;/span&gt; &lt;span class="s2"&gt;"application"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"data-turbo-track"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"reload"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_importmap_tags&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Rails View renders a Glimmer Web Component using the &lt;code&gt;glimmer_component&lt;/code&gt; Rails helper (this is meant to be a drop-in replacement for JS solutions like &lt;code&gt;react_component&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"text-align: center;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Glimmer DSL for Web Rails 7 Sample App&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;glimmer_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sample_selector'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Sample Selector Top-Level Glimmer Web Component is the entry point to the Frontend application, which simply consists of 2 other Glimmer Web Components, the Samples Table (samples_table) and the Highlighted Code (highlighted_code). It is as simple as the code could get, and way simpler and lighter than alternative JavaScript library approaches like React, thus cutting down on maintainability cost and time to delivery significantly, for both small and large apps alike:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web'&lt;/span&gt;

&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'sample_selector/presenters/sample_selector_presenter'&lt;/span&gt;
&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'sample_selector/views/back_anchor'&lt;/span&gt;
&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'sample_selector/views/highlighted_code'&lt;/span&gt;
&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'sample_selector/views/samples_table'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SampleSelector&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Glimmer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Component&lt;/span&gt;

  &lt;span class="n"&gt;before_render&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@presenter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SampleSelectorPresenter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;markup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Run a sample or view a sample's code."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: &lt;/span&gt;&lt;span class="s1"&gt;'text-align: center;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;highlighted_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;language: &lt;/span&gt;&lt;span class="s1"&gt;'ruby'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="vi"&gt;@presenter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;model_code_attribute: :selected_sample_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;float: &lt;/span&gt;&lt;span class="s1"&gt;'right'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;samples_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;presenter: &lt;/span&gt;&lt;span class="vi"&gt;@presenter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Run'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: &lt;/span&gt;&lt;span class="s1"&gt;'margin: 15px 0; padding: 10px; font-size: 1.3em;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;onclick&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prevent_default&lt;/span&gt;
          &lt;span class="n"&gt;markup_root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;
          &lt;span class="no"&gt;BackAnchor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;
          &lt;span class="vi"&gt;@presenter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Highlighted Code Glimmer Web Component declaratively handles loading sample code into an HTML View innerHTML through unidirectional data-binding to the Sample Model code attribute, applying syntax highlighting using highlight.js after reading from the Model whenever updates happen to the View. The code has an excellent separation of concerns between the View and Model, and is a lot simpler than equivalent React code, thus much easier to reason about. Additionally, some CSS was written directly in a Ruby DSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HighlightedCode&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Glimmer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Component&lt;/span&gt;

  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="s1"&gt;'ruby'&lt;/span&gt;
  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:model&lt;/span&gt;
  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:model_code_attribute&lt;/span&gt; &lt;span class="c1"&gt;# name of attribute on model that holds code string to render&lt;/span&gt;
  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="s1"&gt;'initial'&lt;/span&gt;

  &lt;span class="n"&gt;markup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'code-scrollable-container'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: &lt;/span&gt;&lt;span class="s2"&gt;"float: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;pre&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="vi"&gt;@code_element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"language-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;inner_html&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model_code_attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="ss"&gt;after_read: &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;highlight_code&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'div.code-scrollable-container'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;overflow&lt;/span&gt; &lt;span class="s1"&gt;'scroll'&lt;/span&gt;
          &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="s1"&gt;'calc(100vw - 410px)'&lt;/span&gt;
          &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="s1"&gt;'80vh'&lt;/span&gt;
          &lt;span class="n"&gt;border&lt;/span&gt; &lt;span class="s1"&gt;'1px solid rgb(209, 215, 222)'&lt;/span&gt;
          &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'div.code-scrollable-container pre'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;margin&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.hljs-ln td.hljs-ln-line.hljs-ln-numbers'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;user_select&lt;/span&gt; &lt;span class="s1"&gt;'none'&lt;/span&gt;
          &lt;span class="n"&gt;text_align&lt;/span&gt; &lt;span class="s1"&gt;'center'&lt;/span&gt;
          &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="s1"&gt;'rgb(101, 109, 118)'&lt;/span&gt;
          &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="s1"&gt;'3px 30px'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;highlight_code&lt;/span&gt;
    &lt;span class="vi"&gt;@code_element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dom_element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'data-highlighted'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# $$ enables interacting with global JS scope, like top-level hljs variable to use highlight.js library&lt;/span&gt;
    &lt;span class="vg"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hljs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;highlightAll&lt;/span&gt;
    &lt;span class="vg"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hljs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initLineNumbersOnLoad&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Samples Table lists all the samples that are included in the &lt;code&gt;glimmer-dsl-web&lt;/code&gt; Ruby gem, and provides the ability to select a sample and run it. It also interacts with a Sample API Web Service to pull sample code data from the Rails backend, thus ensuring a proper separation of concerns for maximum maintainability. Some CSS is added with a Ruby DSL as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SamplesTable&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Glimmer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Component&lt;/span&gt;

  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:presenter&lt;/span&gt;

  &lt;span class="n"&gt;markup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'samples'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;tbody&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;SampleSelectorPresenter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SAMPLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;tr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;td&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;class_name&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;presenter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:selected_sample&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="ss"&gt;on_read: &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;'selected'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                          &lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="n"&gt;onclick&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
              &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prevent_default&lt;/span&gt;
              &lt;span class="n"&gt;presenter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selected_sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="n"&gt;tr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;# handle this sample differently via links to demonstrate visiting outside pages&lt;/span&gt;
          &lt;span class="n"&gt;td&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello, glimmer_component Rails Helper!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' ( '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Run'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"data-turbo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"false"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;href: &lt;/span&gt;&lt;span class="s1"&gt;'/?address=true&amp;amp;full_name=John%20Doe&amp;amp;street=123%20Main%20St&amp;amp;street2=apt%2012&amp;amp;city=San%20Diego&amp;amp;state=California&amp;amp;zip_code=91911'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' | '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Code'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="ss"&gt;target: &lt;/span&gt;&lt;span class="s1"&gt;'_blank'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="ss"&gt;href: &lt;/span&gt;&lt;span class="s1"&gt;'https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/views/welcomes/_address_page.html.erb'&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' ) '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'table.samples'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;border_spacing&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'table.samples tr td'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;border&lt;/span&gt; &lt;span class="s1"&gt;'1px solid transparent'&lt;/span&gt;
          &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="s1"&gt;'5px'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'table.samples tr td:hover'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;border&lt;/span&gt; &lt;span class="s1"&gt;'1px solid gray'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'table.samples tr.selected td'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;border&lt;/span&gt; &lt;span class="s1"&gt;'1px solid lightgray'&lt;/span&gt;
          &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="s1"&gt;'lightblue'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Back Anchor provides a back-link to enable going back to the main page from any run sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BackAnchor&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Glimmer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Component&lt;/span&gt;

  &lt;span class="n"&gt;markup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;&amp;lt; Back To Samples'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;href: &lt;/span&gt;&lt;span class="s1"&gt;'#'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: &lt;/span&gt;&lt;span class="s1"&gt;'display: block; margin-bottom: 10px;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;back_anchor&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;onclick&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;back_anchor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;
        &lt;span class="no"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'body &amp;gt; *'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:remove&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="no"&gt;SampleSelector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;parent: &lt;/span&gt;&lt;span class="s2"&gt;".sample_selector"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Sample Selector Presenter provides all the data and actions that the Sample Selector View needs, including how to present sample names, the attribute for storing the selected sample, and the method for running a sample, which delegates to the Sample Model to keep concerns better separated for higher maintainability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'../models/sample'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SampleSelectorPresenter&lt;/span&gt;
  &lt;span class="no"&gt;SAMPLE_NAMES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_world'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, World!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_button'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Button!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_form'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Form!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_observer'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Observer!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_observer_data_binding'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Observer (Data-Binding)!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_data_binding'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Data-Binding!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_content_data_binding'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Content Data-Binding!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_component'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Component!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_paragraph'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Paragraph!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_input_date_time'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Input Date/Time!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_form_mvp'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Form (MVP)!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'button_counter'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Button Counter'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="no"&gt;SAMPLES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SAMPLE_NAMES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:selected_sample&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:selected_sample_code&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selected_sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SAMPLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;selected_sample&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# causes selected sample to get highlighted in the View indirectly through data-binding&lt;/span&gt;
    &lt;span class="vi"&gt;@selected_sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt;

    &lt;span class="vi"&gt;@selected_sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch_code&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;# causes selected sample code to display in the View indirectly through data-binding&lt;/span&gt;
      &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selected_sample_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;
    &lt;span class="n"&gt;selected_sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Sample Model stores sample specific data like the code and ID, enables fetching sample code from the Rails Backend using a Sample API Web Service, and provides and the ability to run a sample by loading the associated sample Ruby file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'sample_api'&lt;/span&gt;

&lt;span class="c1"&gt;# Sample Frontend Model&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:code&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="vi"&gt;@id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;code_processor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;SampleApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="vi"&gt;@code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;code&lt;/span&gt;
      &lt;span class="n"&gt;code_processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;
    &lt;span class="c1"&gt;# We must embeded static require/load statements for Opal to pre-load them into page&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="vi"&gt;@id&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_world'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_world.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_world.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_button'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_button.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_button.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_form'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_form.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_form.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_observer'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_observer.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_observer.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_observer_data_binding'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_data_binding'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_content_data_binding'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_content_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_content_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_component'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_component.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_component.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_paragraph'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_paragraph.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_paragraph.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_input_date_time'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_input_date_time.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_input_date_time.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_form_mvp'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_form_mvp.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_form_mvp.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'button_counter'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/regular/button_counter.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/regular/button_counter.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Sample API Web Service simply makes HTTP calls to the Rails backend to grab data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Sample Resource HTTP API that calls Rails Backend Samples API Endpoint&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SampleApi&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sample_processor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/samples/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="c1"&gt;# Wrapping response body with Native to convert from a JS object to an Opal Ruby object, &lt;/span&gt;
        &lt;span class="c1"&gt;# thus converting JS properties into Ruby methods that facilitate interaction with object.&lt;/span&gt;
        &lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sample_processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, we demonstrated in the &lt;a href="https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app"&gt;Sample Selector&lt;/a&gt; app a Rails Frontend application that is written fully in Ruby with Ruby DSLs in place of HTML/CSS/JavaScript, is following the Model-View-Presenter pattern (a variation on MVC), includes HTTP calls to a Rails Backend to demonstrate real Business Use-Cases of Frontend/Backend interaction, and integrates with an external JavaScript library (highlight.js) for Code Syntax Highlighting. &lt;/p&gt;

&lt;p&gt;As a result, Rails Software Engineers do not have to be split anymore between those who are afraid of Frontend Development because of JavaScript, and those who prefer to do Frontend Development in spite of JavaScript's pitfalls. Instead, there is a 3rd better way that unites all Rails Software Engineers! Just write the Frontend in the same language you love so much in the Backend due to offering maximum productivity and maintainability: Ruby! This should become the no-brainer future of all Frontend development in Rails!!!&lt;/p&gt;

&lt;p&gt;I will leave you with the &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web"&gt;Glimmer DSL for Web&lt;/a&gt; introduction from the project README on GitHub:&lt;/p&gt;

&lt;p&gt;"You can finally have Ruby developer happiness and productivity in the Frontend! No more wasting time splitting your resources across multiple languages, using badly engineered, over-engineered, or premature-optimization-obsessed JavaScript libraries, fighting JavaScript build issues (e.g. webpack), or rewriting Ruby Backend code in Frontend JavaScript. With Ruby in the Browser, you can have an exponential jump in development productivity (2x or higher), time-to-release (1/2 or less time), cost (1/2 or cheaper), and maintainability (~50% the code that is simpler and more readable) over JavaScript libraries like React, Angular, Ember, Vue, and Svelte, while being able to reuse Backend Ruby code as is in the Frontend for faster interactions when needed. Ruby in the Browser finally fulfills every highly-productive Rubyist's dream by bringing Ruby productivity fun to Frontend Development, the same productivity fun you had for years and decades in Backend Development."&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>frontend</category>
      <category>glimmer</category>
    </item>
    <item>
      <title>Montreal.rb 2024/03 - Frontend Ruby with Glimmer DSL for Web - Andy Maleh</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Thu, 07 Mar 2024 18:50:15 +0000</pubDate>
      <link>https://dev.to/andyobtiva/montrealrb-202403-frontend-ruby-with-glimmer-dsl-for-web-andy-maleh-58p6</link>
      <guid>https://dev.to/andyobtiva/montrealrb-202403-frontend-ruby-with-glimmer-dsl-for-web-andy-maleh-58p6</guid>
      <description>&lt;p&gt;The talk video and slides have been posted for the Montreal.rb March 2024 talk "Frontend Ruby with &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web"&gt;Glimmer DSL for Web&lt;/a&gt;" (Ruby in the Browser Web Frontend Framework).&lt;/p&gt;

&lt;p&gt;YouTube Video :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=rIZ-ILUv9ME&amp;amp;list=PLRAf4zt5oEjc2mqmEN9m_O0JovQCXxvxt&amp;amp;index=11"&gt;https://www.youtube.com/watch?v=rIZ-ILUv9ME&amp;amp;list=PLRAf4zt5oEjc2mqmEN9m_O0JovQCXxvxt&amp;amp;index=11&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google Slides :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/presentation/d/e/2PACX-1vQVihtMktOEJ-AJWb1a-uyJfpyn7q92xstcx7QLIUOFONzG5TmKD7_2hSLdwijgw-l6LdK6OLbQPP61/pub?start=false&amp;amp;loop=false&amp;amp;delayms=60000"&gt;https://docs.google.com/presentation/d/e/2PACX-1vQVihtMktOEJ-AJWb1a-uyJfpyn7q92xstcx7QLIUOFONzG5TmKD7_2hSLdwijgw-l6LdK6OLbQPP61/pub?start=false&amp;amp;loop=false&amp;amp;delayms=60000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blog Post Announcement :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://andymaleh.blogspot.com/2024/03/montrealrb-march-2024-frontend-ruby.html"&gt;https://andymaleh.blogspot.com/2024/03/montrealrb-march-2024-frontend-ruby.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Talk Description :&lt;/p&gt;

&lt;p&gt;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!&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>glimmer</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Slides &amp; Code for RubyConf 2023 Workshop "How To Build Desktop Applications in Ruby"</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Wed, 15 Nov 2023 03:49:21 +0000</pubDate>
      <link>https://dev.to/andyobtiva/slides-code-for-rubyconf-2023-workshop-how-to-build-desktop-applications-in-ruby-2923</link>
      <guid>https://dev.to/andyobtiva/slides-code-for-rubyconf-2023-workshop-how-to-build-desktop-applications-in-ruby-2923</guid>
      <description>&lt;p&gt;Thanks to everyone who attended my RubyConf 2023 2-Hour Workshop "How To Build Desktop Applications in Ruby". For those who missed the event, I posted the presentation slides and code exercises (27 exercises) on GitHub. I also blogged about the new Color The Circles game app that was developed at the RubyConf 2023 Community Day Glimmer Desktop Hacking event.&lt;/p&gt;

&lt;p&gt;More at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://andymaleh.blogspot.com/2023/11/rubyconf-2023-how-to-build-desktop.html"&gt;https://andymaleh.blogspot.com/2023/11/rubyconf-2023-how-to-build-desktop.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub Repo Direct Link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby"&gt;https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Presentation Slides Direct Link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bit.ly/rubyconf2023desktop"&gt;https://bit.ly/rubyconf2023desktop&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>conference</category>
      <category>desktop</category>
      <category>workshop</category>
    </item>
  </channel>
</rss>
