glimmer-dsl-web 0.6.5 → 0.6.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6eb86fb33f7053193df400df56389ceaecad3b8857b7e110da57353682f9d7a3
4
- data.tar.gz: f713f308fbb0cf9fbdd5f965465e8d875571fc07a2b126e38403236124b047f2
3
+ metadata.gz: 542796633baef10477c8cda0c134586e6fda1cb7b9b335d618525fa889f14f2b
4
+ data.tar.gz: c35bc5b7d2a1290e700fea1853470f102351993d4a9747764a16b560bca36050
5
5
  SHA512:
6
- metadata.gz: 98b0322be04f66756a304156880507c6f9cff290337d734709c3c6742693b0d0129e0e2a4c1af5e286ea41495e7c8064741d48f4e2e6d361049659d3619b0d3d
7
- data.tar.gz: 05161d53f0d4a57a9b6c460ca6eef9a5a5e6606cfc21245ef77ca0c1720bac0116f619eccdf7b3e2a85018056e07a8e5525e23e05035edde0b84126b5ccb37c8
6
+ metadata.gz: eb2ed76d330dc4b503890e216d352210fd50fe2a1590883df31964853c7bd707857fc201c6ae102a507ed844bcd94537f318a86682a874f66448206bafa90bd0
7
+ data.tar.gz: f5836f4e4e8f0d377f54e1a16198a29bf0db10c28dc23a4a758435809ebc48b8982e882bcc1e408dce6d79db1ed11b5df237e8ee7f404a4e1f72fff5eab4f298
data/CHANGELOG.md CHANGED
@@ -1,10 +1,16 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.6.6
4
+
5
+ - `Rails::ResourceService` supports index/show/create/update/destory REST API calls for any Rails resources
6
+ - Support being able to set or data-bind `title` property on HTML elements
7
+ - Restrict use of `title` tag to within a `head` element only
8
+
3
9
  ## 0.6.5
4
10
 
5
11
  - Ensure clearing input datetime/date/time/month values sends `nil` to the data-bound model attribute (not `''`, which caused issues)
6
- - Support data-binding input month vaue to a model attribute that has a datetime value
7
- - Fix issue with clearing date/time from Hello, Input Date/Time! causing errors in the web browser console
12
+ - Support data-binding input month value to a model attribute that has a datetime value
13
+ - Fix issue with clearing date/time in Hello, Input Date/Time! causing errors in the web browser console
8
14
 
9
15
  ## 0.6.4
10
16
 
data/README.md CHANGED
@@ -1,23 +1,27 @@
1
- # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Web 0.6.5 (Beta)
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Web 0.6.6 (Beta)
2
2
  ## Ruby-in-the-Browser Web Frontend Framework
3
- ### The "Rails" of Frontend Frameworks!!!
3
+ ### The "Rails" of Frontend Frameworks!!! ([Fukuoka Award Winning](https://andymaleh.blogspot.com/2025/01/glimmer-dsl-for-web-wins-in-fukuoka.html))
4
4
  #### Finally, Ruby Developer Productivity, Happiness, and Fun in the Frontend!!!
5
5
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-web.svg)](http://badge.fury.io/rb/glimmer-dsl-web)
6
6
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
7
7
 
8
8
  **(Based on Original [Glimmer](https://github.com/AndyObtiva/glimmer) Library Handling World’s Ruby GUI Needs Since 2007. Beware of Imitators!)**
9
9
 
10
+ **([Fukuoka Prefecture Future IT Initiative 2025 Money Forward Award Winner](https://andymaleh.blogspot.com/2025/01/glimmer-dsl-for-web-wins-in-fukuoka.html))**
11
+
10
12
  **(Talk Videos: [Intro to Ruby in the Browser](https://youtu.be/4AdcfbI6A4c?si=MmxOrkhIXTDHQoYi) / [Frontend Ruby with Glimmer DSL for Web \[Montreal.rb\]](https://youtu.be/rIZ-ILUv9ME?si=raygUXVPd_7ypWuE) / [Frontend Ruby with Glimmer DSL for Web \[/dev/mtl 2024\]](https://www.youtube.com/watch?v=J2VIY9DMJo4))**
11
13
 
12
14
  **(Ruby Rogues Podcast: [Building Better Ruby Apps: Glimmer Component Slots and More](https://topenddevs.com/podcasts/ruby-rogues/episodes/building-better-ruby-apps-glimmer-s-component-slots-and-more-ruby-653))**
13
15
 
14
16
  [![Todo MVC](/images/glimmer-dsl-web-samples-regular-todo-mvc.gif)](https://sample-glimmer-dsl-web-rails7-app-black-sound-6793.fly.dev/)
15
17
 
18
+ **Endorsement:** *"I'd like to endorse Andy Maleh’s work (Glimmer DSL for Web). I got introduced to it at RubyConf 2024 and have been playing around with it pretty successfully. What I have found most interesting is that I have been writing inside of a rails app, where I have been running the same code for models and presenters inside of MRI rspec. That way I can write tests that verify behavior of the presenters and models and still see them run successfully in the browser. That allows me to have a very nice cycle of refactoring and being confident in my changes without even running it in browser. I just assume that the binding will work and it usually works perfectly."* - Steve Tuckner on January 9, 2024
19
+
16
20
  You can finally live in pure Rubyland on the Web in both the frontend and backend with [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web)! [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Web enables building Web Frontends (aka SPA: Single Page Applications) using [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c), as per [Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby](https://youtu.be/knutsgHTrfQ?t=789). It supports Rails' principle of the One Person Framework by not requiring any extra developers with JavaScript expertise, yet enabling Ruby (Backend) Software Engineers to develop the Frontend with Ruby code that is better than any JavaScript code produced by JS developers. It aims at providing the simplest, most intuitive, most straight-forward, and most productive frontend framework in existence. The framework follows the Ruby way (with [DSLs](https://martinfowler.com/books/dsl.html) and [TIMTOWTDI](https://en.wiktionary.org/wiki/TMTOWTDI#English)) and the Rails way ([Convention over Configuration](https://rubyonrails.org/doctrine)) in building Isomorphic Ruby on Rails Applications. It provides a Ruby [HTML DSL](#usage) (including full support for [SVG](#hello-svg)), which uniquely enables writing both structure code and logic code in one language. It supports both Unidirectional (One-Way) [Data-Binding](#hello-data-binding) (using `<=`) and Bidirectional (Two-Way) [Data-Binding](#hello-data-binding) (using `<=>`). Dynamic rendering (and re-rendering) of HTML content is also supported via [Content Data-Binding](#hello-content-data-binding). Modular design is supported with [Glimmer Web Components](#hello-component), [Component Slots](#hello-component-slots), and [Component Custom Event Listeners](#hello-component-listeners). And, a Ruby CSS DSL is supported with the included [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css). To automatically convert legacy HTML & CSS code to Glimmer DSL Ruby code, Software Engineers could use the included [`html_to_glimmer`](https://github.com/AndyObtiva/glimmer-dsl-xml#html-to-glimmer-converter) and [`css_to_glimmer`](https://github.com/AndyObtiva/glimmer-dsl-css#css-to-glimmer-converter) commands. Many [samples](#samples) are demonstrated in the [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) (there is a very minimal [Standalone [No Rails] static site sample app](https://github.com/Largo/glimmer-dsl-web-standalone-demo) too).
17
21
 
18
22
  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](https://www.youtube.com/watch?v=4AdcfbI6A4c), 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. Also, with Frontend Ruby SPA (Single Page Applications), companies can cut their hiring budget in half by having Backend Ruby Software Engineers do Frontend Development in Ruby! [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c) finally fulfills every smart 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.
19
23
 
20
- [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) aims to be a very simple Ruby-based SPA drop-in replacement for your existing JavaScript Frontend SPA library (e.g. React, Angular, Vue, Ember, Svelte) or your JavaScript Frontend layer in general. It does not change how your Frontend interacts with the Backend, meaning you can continue to write Rails Backend API endpoints as needed and make HTTP/Ajax requests or read data embedded in elements, but from [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c). Whatever is possible in JavaScript is possible when using Glimmer DSL for Web as it integrates with any existing JavaScript library. The [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) demonstrates how to [make HTTP calls](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector/models/sample_api.rb) and how to [integrate with a JavaScript library](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/views/layouts/application.html.erb) (highlightjs) that performs [code syntax highlighting](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector.rb). [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) currently runs on [Opal](https://opalrb.com/) ([Fukuoka Ruby 2023 Award Winner](https://www.digitalfukuoka.jp/topics/228?locale=ja)), a Ruby-to-JavaScript transpiler. In the future, it might support other Frontend Ruby environments, such as [ruby.wasm](https://github.com/ruby/ruby.wasm).
24
+ [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) aims to be a very simple Ruby-based SPA drop-in replacement for your existing JavaScript Frontend SPA library (e.g. React, Angular, Vue, Ember, Svelte) or your JavaScript Frontend layer in general. It does not change how your Frontend interacts with the Backend, meaning you can continue to write Rails Backend API endpoints as needed and make HTTP/Ajax requests or read data embedded in elements, but from [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c). Whatever is possible in JavaScript is possible when using Glimmer DSL for Web as it integrates with any existing JavaScript library. The [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) demonstrates how to [make HTTP calls](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector/models/sample_api.rb) or [Rails REST API index/show/create/update/destroy web requests for Resources](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/contact_manager/presenters/contact_presenter.rb) via [Rails::ResourceService](/lib/rails/resource_service.rb) and how to [integrate with a JavaScript library](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/views/layouts/application.html.erb) (highlightjs) that performs [code syntax highlighting](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector.rb). [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) currently runs on [Opal](https://opalrb.com/) ([Fukuoka Ruby 2023 Award Winner](https://www.digitalfukuoka.jp/topics/228?locale=ja)), a Ruby-to-JavaScript transpiler. In the future, it might support other Frontend Ruby environments, such as [ruby.wasm](https://github.com/ruby/ruby.wasm).
21
25
 
22
26
  After looking through the [samples](#samples) below, read the [FAQ (Frequently Asked Questions)](#faq) to learn more about how Glimmer DSL for Web compares to other approaches/libraries like Hotwire (Turbo), Phlex, ViewComponent, Angular, Vue, React, Svelte, and other JS frameworks.
23
27
 
@@ -1377,11 +1381,11 @@ Learn more about the differences between various [Glimmer](https://github.com/An
1377
1381
 
1378
1382
  ## Setup
1379
1383
 
1380
- You can setup Glimmer DSL for Web in [Rails 7](#rails-7), [Rails 6](#rails-6), or [Standalone (No Rails)](#standalone-no-rails).
1384
+ You can setup Glimmer DSL for Web in [Rails 7](#rails-7) or [Standalone (No Rails)](#standalone-no-rails).
1381
1385
 
1382
1386
  Once done, read [Usage](#usage) instructions. Note that for serious app usage, it is recommended to build [components](#hello-component) and use the [`glimmer_component` Rails Helper](#hello-glimmer_component-rails-helper) to embed the top-level Web Frontend component in a Rails View.
1383
1387
 
1384
- (NOTE: Keep in mind this is a Beta. If you run into issues, try to go back to a [previous revision](https://rubygems.org/gems/glimmer-dsl-web/versions). Also, there is a slight chance any issues you encounter are fixed in master or some other branch that you could check out instead)
1388
+ (NOTE: Keep in mind this is a Beta. If you run into issues, read the [FAQ](#faq) in case they are addressed there (e.g. [I sometimes get an Opal error that makes no sense in relation to my code. How do I fix it?](https://github.com/AndyObtiva/glimmer-dsl-web/blob/master/README.md#i-sometimes-get-an-opal-error-that-makes-no-sense-in-relation-to-my-code-how-do-i-fix-it)) and try to go back to a [previous revision](https://rubygems.org/gems/glimmer-dsl-web/versions). Also, there is a slight chance any issues you encounter are fixed in master or some other branch that you could check out instead)
1385
1389
 
1386
1390
  ### Rails 7
1387
1391
 
@@ -1404,7 +1408,7 @@ rails new glimmer_app_server
1404
1408
  Add the following to `Gemfile`:
1405
1409
 
1406
1410
  ```
1407
- gem 'glimmer-dsl-web', '~> 0.6.5'
1411
+ gem 'glimmer-dsl-web', '~> 0.6.6'
1408
1412
  ```
1409
1413
 
1410
1414
  Run:
@@ -1616,6 +1620,8 @@ Andreas Idogawa-Wildi ([@Largo](https://github.com/Largo)) created a project tha
1616
1620
 
1617
1621
  ## Usage
1618
1622
 
1623
+ ### Glimmer HTML DSL
1624
+
1619
1625
  Glimmer DSL for Web offers a HTML DSL ([Graphical User Interface](https://en.wikipedia.org/wiki/Graphical_user_interface) [Domain Specific Language](https://en.wikipedia.org/wiki/Domain-specific_language)) for building HTML Web User Interfaces declaratively in Ruby.
1620
1626
 
1621
1627
  1- **Keywords (HTML Elements)**
@@ -1690,6 +1696,40 @@ Next, check out [Samples](#samples).
1690
1696
 
1691
1697
  Note that for serious app usage, it is recommended to build [components](#hello-component) and use the [`glimmer_component` Rails Helper](#hello-glimmer_component-rails-helper) to embed the top-level Web Frontend component in a Rails View.
1692
1698
 
1699
+ ### Rails::ResourceService
1700
+
1701
+ To make REST API calls (web requests) to the Backend of a Rails application in order to index/show/create/update/delete resources,
1702
+ you can use [Rails::ResourceService](/lib/rails/resource_service.rb) (`require 'rails/resource_service'` to use). Consult
1703
+ the `Rails::ResourceService` class source code to find out what its API is. It can work with a basic Rails Scaffold of a Resource
1704
+ if Developers would rather not write the Backend by hand.
1705
+
1706
+ Example from [ContactPresenter](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/contact_manager/presenters/contact_presenter.rb) in the [Contact Manager](#contact-manager) sample:
1707
+
1708
+ `form_contact` is an instance of the [Contact](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/contact_manager/models/contact.rb) class.
1709
+
1710
+ ```ruby
1711
+ Rails::ResourceService.update(resource: form_contact) do |response|
1712
+ if response.ok?
1713
+ updated_contact_response_body = Native(response.body)
1714
+ updated_contact = form_contact.clone
1715
+ updated_contact.updated_at = updated_contact_response_body.updated_at
1716
+ contacts[edit_index].load_with(updated_contact)
1717
+ self.edit_index = nil
1718
+ form_contact.reset
1719
+ form_contact.errors = nil
1720
+ else
1721
+ form_contact.errors = JSON.parse(response.body)
1722
+ end
1723
+ end
1724
+ ```
1725
+
1726
+ Note that there are alternative ways of invoking the `Rails::ResourceService.update` call:
1727
+ - `Rails::ResourceService.update(resource: form_contact)`
1728
+ - `Rails::ResourceService.update(resource_class: Contact, resource_id: form_contact.id, resource_attributes: {first_name: form_contact.first_name, ...})`
1729
+ - `Rails::ResourceService.update(singular_resource_name: 'contact', resource_id: form_contact.id, resource_attributes: {first_name: form_contact.first_name, ...})`
1730
+ - `Rails::ResourceService.update(update_resource_url: "/contacts/#{form_contact.id}.json", resource_attributes: {first_name: form_contact.first_name, ...})`
1731
+ - `Rails::ResourceService.update(update_resource_url: "/contacts/#{form_contact.id}.json", params: {contact: {first_name: form_contact.first_name, ...}})`
1732
+
1693
1733
  ## Supported Glimmer DSL Keywords
1694
1734
 
1695
1735
  [All HTML elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element), following the Ruby method name standard of lowercase and underscored names.
@@ -4503,6 +4543,18 @@ end
4503
4543
 
4504
4544
  ![Todo MVC](/images/glimmer-dsl-web-samples-regular-todo-mvc.gif)
4505
4545
 
4546
+ #### Contact Manager
4547
+
4548
+ The Contact Manager sample demonstrates talking to the Rails Backend by making create/update/destory REST API calls
4549
+ to RESTful Resources via the `Rails::ResourceService` class that is included in Glimmer DSL for Web
4550
+ (`require 'rails/resource_service'` to use).
4551
+
4552
+ [https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/contact_manager.rb](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/contact_manager.rb)
4553
+
4554
+ [https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/contact_manager](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/contact_manager)
4555
+
4556
+ ![contact manager](/images/glimmer-dsl-web-samples-regular-contact-manager.gif)
4557
+
4506
4558
  ## Design Principles
4507
4559
 
4508
4560
  - The Ruby Way (including TIMTOWTDI: There Is More Than One Way To Do It)
@@ -4544,30 +4596,33 @@ Learn more by reading the [GPG](https://github.com/AndyObtiva/glimmer/blob/maste
4544
4596
 
4545
4597
  F.A.Q. (Frequently Asked Questions):
4546
4598
 
4547
- **Can I reuse JavaScript libraries from Glimmer DSL for Web in Ruby?**
4599
+ #### Can I reuse JavaScript libraries from Glimmer DSL for Web in Ruby?
4548
4600
 
4549
4601
  Absolutely. Glimmer DSL for Web can integrate with any JavaScript libraries. You can either load the JavaScript libraries in advance by linking to them in the Rails View/Layout (e.g. linking to JS library CDN URLs) or by including JavaScript files in the lookup directories of Opal Ruby, and adding a Ruby `require('path_to_js_lib')` call in the code. In Ruby, the `$$` global variable gives access to the top-level JavaScript global scope, which enables invocations on any JavaScript objects. For example, `$$.hljs` gives access to the loaded `window.hljs` object for the Highlight.js library, and that enables invoking any functions from that library as needed, like `$$.hljs.highlightAll` to activate code syntax highlighting.
4550
4602
 
4551
- **How does Glimmer DSL for Web compare to Rails Hotwire (Turbo)?**
4603
+ #### How does Glimmer DSL for Web compare to Rails Hotwire (Turbo)?
4552
4604
 
4553
4605
  Glimmer DSL for Web is a Frontend library, meaning it replaces the JavaScript layer in a web application (e.g. Rails app) with Ruby code. On the other hand, Rails Hotwire (Turbo) is mostly a Backend-driven technology that enables automatically replacing HTML DOM elements with HTML markup sent over the wire from a Rails Backend. So, the two technologies are mostly orthogonal, but can be used in the same Rails web application, albeit exclusively on separate web pages at the moment. In the future, we might explore supporting the ability to combine both technologies in the same pages, but until then, use on separate pages. Glimmer DSL for Web can handle any sort of Frontend interactions even without making HTTP calls to the Backend, so it can implement more use-cases than Hotwire. Using Glimmer DSL for Web with Rails API end-points is simpler than using Hotwire overall. That is because Glimmer Content Data-Binding is a simpler version of Turbo Frames that does not require worrying about setting and using element IDs (as that is handled automatically) and that operates at a more correct abstraction level for how we think about View component updates in relation to Model changes (we make updates at the Model layer, and they automatically get reflected in the View through data-binding). Also, Glimmer DSL for Web supports Glimmer Web Components, which enable better division and organization of View code into modular components than ERB plus having higher readability. It is true that Hotwire is an improvement over using JavaScript frameworks like React when there is not much logic beyond updating elements with Server-Side rendered HTML. And, Glimmer DSL for Web is the next big advancement that provides an even simpler approach while also giving you full Frontend Development capabilities using Ruby in the Browser.
4554
4606
 
4555
- **How does Glimmer DSL for Web compare to Phlex or ViewComponent?**
4607
+ #### How does Glimmer DSL for Web compare to Phlex or ViewComponent?
4556
4608
 
4557
4609
  Glimmer DSL for Web is a Frontend library, meaning it replaces the JavaScript layer in a web application (e.g. Rails app) with Ruby code while providing its own View-layer component support using [`Glimmer::Web::Component`](#hello-component). On the other hand, Phlex and ViewComponent are Backend View-layer component libraries, so they serve 100% orthogonal needs, and can be used side by side with Glimmer DSL for Web if needed (e.g. Phlex components can consist of Backend HTML elements + Glimmer components that are rendered in the Frontend). That said, Phlex came out years after previous Glimmer libraries like Glimmer DSL for SWT, and Phlex's component system is very similar to Glimmer's component system in Glimmer DSL for SWT (perhaps inspired by it unconsciously or consciously). So, if you like Phlex in the Backend, you'll love Glimmer DSL for Web in the Frontend.
4558
4610
 
4559
- **How does Glimmer DSL for Web compare to Angular, React, Vue, Svelte, or other JS frameworks?**
4611
+ #### How does Glimmer DSL for Web compare to Angular, React, Vue, Svelte, or other JS frameworks?
4560
4612
 
4561
4613
  Without delving into details, Glimmer DSL for Web is meant to be a Ruby-based drop-in replacement for Angular, React, Vue, Svelte, and other JS frameworks. Glimmer Ruby code is transpiled to JavaScript, so it has JavaScript performance in general, which is not that far from that of Angular, React, or Vue. Glimmer DSL for Web has outperformed React by a factor of 33.33% in rendering 3000+ elements in a realistic app scenario that was benchmarked recently (in Oct 2024). Additionally, it enables writing both structure code and logic code in the same language (Ruby), greatly simplifying maintainability and improving productivity by eliminating multi-language dissonance and friction that drags down productivity as there is no need anymore to think in multiple languages unnecessarily, use XML based solutions (e.g. JSX), or use templating solutions (e.g. Mustache). Lastly, Glimmer DSL for Web supports familiar Software Engineering architectural patterns like Model-View-Controller and Model-View-Presenter, enabling Software Engineers to write the lightest and simplest code possible for building Web frontends in Ruby, with the best separation of concerns. Software Engineers can finally become happy Ruby developers by writing Ruby code in the Frontend too now in addition to the Backend.
4562
4614
 
4563
- **How do I have a Glimmer Web Component re-render in a similar way to how React components re-render?**
4615
+ #### How do I have a Glimmer Web Component re-render in a similar way to how React components re-render?
4564
4616
 
4565
4617
  [Content Data-Binding](#hello-content-data-binding) supports re-rendering dynamic parts of a Glimmer Web Component (or the full component if all of it is dynamic). Glimmer DSL for Web simplifies Frontend Development significantly over React by not re-rendering everything if not needed (regardless of use of Virtual DOM) yet only re-rendering the parts of a component that do change dynamically. As a result, Software Engineers do not have to worry about the ripple effect of full re-renders or the possibility of breaking some parts of a page when making small changes to a single component in a hierarchy of page components. And, if only an element property changes, [Content Data-Binding](#hello-content-data-binding) is not even needed. It is much simpler to rely on simple [Property Data-Binding](#hello-data-binding) in that case. This makes reasoning about Glimmer DSL for Web Ruby code a lot simpler than reasoning about React component JavaScript code.
4566
4618
 
4567
- **How do I reuse React components from Glimmer DSL for Web?**
4619
+ #### How do I reuse React components from Glimmer DSL for Web?
4568
4620
 
4569
4621
  In the future, support for HTML Web Components will be added, and that will enable reuse of React components by using a library that converts them to HTML Web Components first like [react-to-web-component](https://github.com/bitovi/react-to-web-component) or [react-webcomponent](https://github.com/adobe/react-webcomponent).
4570
4622
 
4623
+ #### I sometimes get an Opal error that makes no sense in relation to my code. How do I fix it?
4624
+
4625
+ That happens randomly sometimes (e.g. `Uncaught SyntaxError: Unexpected token ':'`) because of a bug in Sprockets caching of Opal assets (which has been reported to the Opal team). To get around it, try first to restart the Rails server and then refresh the page. If that does not resolve the issue, stop the Rails server, clear tmp/cache (run `rm -rf tmp/cache` to clear cache generated by Opal), start the Rails server again, and refresh the page. This should definitely resolve the issue if it was indeed not caused by your code, yet by the Opal Sprockets caching bug.
4571
4626
 
4572
4627
  ### Issues
4573
4628
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.5
1
+ 0.6.6
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: glimmer-dsl-web 0.6.5 ruby lib
5
+ # stub: glimmer-dsl-web 0.6.6 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "glimmer-dsl-web".freeze
9
- s.version = "0.6.5"
9
+ s.version = "0.6.6"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Andy Maleh".freeze]
14
- s.date = "2025-01-20"
14
+ s.date = "2025-02-17"
15
15
  s.description = "Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework) enables building Web Frontends using Ruby in the Browser, as per Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby. It aims at providing the simplest, most intuitive, most straight-forward, and most productive frontend framework in existence. The framework follows the Ruby way (with DSLs and TIMTOWTDI) and the Rails way (Convention over Configuration) in building Isomorphic Ruby on Rails Applications. It provides a Ruby HTML DSL, which uniquely enables writing both structure code and logic code in one language. It supports both Unidirectional (One-Way) Data-Binding (using <=) and Bidirectional (Two-Way) Data-Binding (using <=>). Dynamic rendering (and re-rendering) of HTML content is also supported via Content Data-Binding. Modular design is supported with Glimmer Web Components, Component Slots, and Component Custom Event Listeners. And, a Ruby CSS DSL is supported with the included Glimmer DSL for CSS. Many samples are demonstrated in the Rails sample app (there is a very minimal Standalone [No Rails] sample app too). You can finally live in pure Rubyland on the Web in both the frontend and backend with Glimmer DSL for Web! This gem relies on Opal Ruby.".freeze
16
16
  s.email = "andy.am@gmail.com".freeze
17
17
  s.extra_rdoc_files = [
@@ -93,7 +93,8 @@ Gem::Specification.new do |s|
93
93
  "lib/glimmer/web/element_proxy.rb",
94
94
  "lib/glimmer/web/event_proxy.rb",
95
95
  "lib/glimmer/web/formatting_element_proxy.rb",
96
- "lib/glimmer/web/listener_proxy.rb"
96
+ "lib/glimmer/web/listener_proxy.rb",
97
+ "lib/rails/resource_service.rb"
97
98
  ]
98
99
  s.homepage = "http://github.com/AndyObtiva/glimmer-dsl-web".freeze
99
100
  s.licenses = ["MIT".freeze]
@@ -25,6 +25,11 @@ module Glimmer
25
25
  args.size == 1 && args.first.is_a?(Hash) ||
26
26
  args.size == 2 && args.first.is_a?(String) && args.last.is_a?(Hash)
27
27
  ) &&
28
+ (
29
+ keyword != 'title' ||
30
+ parent.nil? ||
31
+ parent.keyword == 'head'
32
+ ) &&
28
33
  ( # ensure SVG keywords only live under SVG element (unless it's the SVG element itself)
29
34
  !Glimmer::Web::ElementProxy.svg_keyword_supported?(keyword) ||
30
35
  keyword == 'svg' ||
@@ -131,6 +131,9 @@ module Glimmer
131
131
  ].map(&:downcase)
132
132
 
133
133
  ELEMENT_KEYWORDS = HTML_ELEMENT_KEYWORDS + SVG_ELEMENT_KEYWORDS
134
+
135
+ # title is a special attribute because it matches an element tag name (needs special treatment)
136
+ HTML_ELEMENT_SPECIAL_ATTRIBUTES = ['title']
134
137
 
135
138
  GLIMMER_ATTRIBUTES = [:parent]
136
139
  PROPERTY_ALIASES = {
@@ -732,7 +735,13 @@ module Glimmer
732
735
  # TODO consider doing more correct checking of availability of properties/methods using native ticks
733
736
  property_name = property_name_for(method_name)
734
737
  unnormalized_property_name = unnormalized_property_name_for(method_name)
735
- if method_name.to_s.start_with?('class_name_')
738
+ if method_name.end_with?('=') && HTML_ELEMENT_SPECIAL_ATTRIBUTES.include?(property_name)
739
+ if rendered?
740
+ dom_element.attr(property_name, *args)
741
+ else
742
+ enqueue_post_render_method_call(method_name, *args, &block)
743
+ end
744
+ elsif method_name.to_s.start_with?('class_name_')
736
745
  property, sub_property = method_name.to_s.match(REGEX_CLASS_NAME_SUB_PROPERTY).to_a.drop(1)
737
746
  if args.empty?
738
747
  class_name_included(sub_property)
@@ -0,0 +1,76 @@
1
+ module Rails
2
+ # ResourceService supports index/show/create/update/destory REST API calls for any Rails resources
3
+ # Automatically loads the authenticity token from meta[name=csrf-token] content attribute
4
+ # Assumes a resource or resource class that matches the name of a Backend ActiveRecord Model (e.g. Contact class or instance)
5
+ class ResourceService
6
+ TIMESTAMP_ATTRIBUTES = ['created_at', 'updated_at']
7
+
8
+ class << self
9
+ def index(resource: nil, resource_class: nil, singular_resource_name: nil, plural_resource_name: nil, index_resource_url: nil, params: nil, &response_handler)
10
+ resource_class ||= resource&.class
11
+ singular_resource_name ||= singular_resource_name_for_resource_class(resource_class)
12
+ plural_resource_name ||= "#{singular_resource_name}s"
13
+ index_resource_url ||= "/#{plural_resource_name}.json"
14
+ HTTP.get(index_resource_url, payload: index_show_destroy_resource_params(params: params.to_h), &response_handler)
15
+ end
16
+
17
+ def show(resource: nil, resource_class: nil, resource_id: nil, singular_resource_name: nil, plural_resource_name: nil, show_resource_url: nil, params: nil, &response_handler)
18
+ resource_class ||= resource&.class
19
+ resource_id ||= resource&.id
20
+ singular_resource_name ||= singular_resource_name_for_resource_class(resource_class)
21
+ plural_resource_name ||= "#{singular_resource_name}s"
22
+ show_resource_url ||= "/#{plural_resource_name}/#{resource_id}.json"
23
+ HTTP.get(show_resource_url, payload: index_show_destroy_resource_params(params: params.to_h), &response_handler)
24
+ end
25
+
26
+ def create(resource: nil, resource_class: nil, resource_attributes: nil, singular_resource_name: nil, plural_resource_name: nil, create_resource_url: nil, params: nil, &response_handler)
27
+ resource_class ||= resource&.class
28
+ singular_resource_name ||= singular_resource_name_for_resource_class(resource_class)
29
+ plural_resource_name ||= "#{singular_resource_name}s"
30
+ create_resource_url ||= "/#{plural_resource_name}.json"
31
+ HTTP.post(create_resource_url, payload: create_update_resource_params(resource:, resource_class:, resource_attributes:, singular_resource_name:, params: params.to_h), &response_handler)
32
+ end
33
+
34
+ def update(resource: nil, resource_class: nil, resource_id: nil, resource_attributes: nil, singular_resource_name: nil, plural_resource_name: nil, update_resource_url: nil, params: nil, &response_handler)
35
+ resource_class ||= resource&.class
36
+ resource_id ||= resource&.id
37
+ singular_resource_name ||= singular_resource_name_for_resource_class(resource_class)
38
+ plural_resource_name ||= "#{singular_resource_name}s"
39
+ update_resource_url ||= "/#{plural_resource_name}/#{resource_id}.json"
40
+ HTTP.patch(update_resource_url, payload: create_update_resource_params(resource:, resource_class:, resource_attributes:, singular_resource_name:, params: params.to_h), &response_handler)
41
+ end
42
+
43
+ def destroy(resource: nil, resource_class: nil, resource_id: nil, singular_resource_name: nil, plural_resource_name: nil, destroy_resource_url: nil, params: nil, &response_handler)
44
+ resource_class ||= resource&.class
45
+ resource_id ||= resource&.id
46
+ singular_resource_name ||= singular_resource_name_for_resource_class(resource_class)
47
+ plural_resource_name ||= "#{singular_resource_name}s"
48
+ destroy_resource_url ||= "/#{plural_resource_name}/#{resource_id}.json"
49
+ HTTP.delete(destroy_resource_url, payload: index_show_destroy_resource_params(params: params.to_h), &response_handler)
50
+ end
51
+
52
+ def index_show_destroy_resource_params(params: nil)
53
+ {authenticity_token:}.merge(params.to_h)
54
+ end
55
+
56
+ def create_update_resource_params(resource: nil, resource_class: nil, resource_attributes: nil, singular_resource_name: nil, params: nil)
57
+ resource_class ||= resource&.class
58
+ singular_resource_name ||= singular_resource_name_for_resource_class(resource_class)
59
+ resource_params = {authenticity_token:}
60
+ resource_attributes ||= resource&.to_h&.reject { |attribute, value| TIMESTAMP_ATTRIBUTES.include?(attribute) }
61
+ resource_params[singular_resource_name] = resource_attributes.to_h
62
+ resource_params = resource_params.merge(params.to_h)
63
+ resource_params
64
+ end
65
+
66
+ def authenticity_token
67
+ Element['meta[name=csrf-token]'].attr('content')
68
+ end
69
+
70
+ def singular_resource_name_for_resource_class(resource_class)
71
+ return nil if resource_class.nil?
72
+ resource_class.to_s.split('::').last.downcase
73
+ end
74
+ end
75
+ end
76
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-20 00:00:00.000000000 Z
11
+ date: 2025-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -328,6 +328,7 @@ files:
328
328
  - lib/glimmer/web/event_proxy.rb
329
329
  - lib/glimmer/web/formatting_element_proxy.rb
330
330
  - lib/glimmer/web/listener_proxy.rb
331
+ - lib/rails/resource_service.rb
331
332
  homepage: http://github.com/AndyObtiva/glimmer-dsl-web
332
333
  licenses:
333
334
  - MIT