Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/bkuhlmann/htmx

An augmenter and companion to the HTMX JavaScript library.
https://github.com/bkuhlmann/htmx

htmx hypermedia rest ruby

Last synced: about 2 months ago
JSON representation

An augmenter and companion to the HTMX JavaScript library.

Awesome Lists containing this project

README

        

:toc: macro
:toclevels: 5
:figure-caption!:

:htmx_link: link:https://htmx.org[HTMX]
:hypermedia_systems_link: link:https://hypermedia.systems[Hypermedia Systems]
:hanami_link: link:https://hanamirb.org[Hanami]
:roda_link: link:http://roda.jeremyevans.net[Roda]
:data_link: link:https://alchemists.io/articles/ruby_data[Data]
:hanamismith_link: link:https://alchemists.io/projects/hanamismith[Hanamismith]

= HTMX

A haiku from the {htmx_link} team:

....
javascript fatigue:
longing for a hypertext
already in hand
....

...and from {hypermedia_systems_link}:

____
The goal of [HTMX] is not less JavaScript, but less code, more readable and hypermedia-friendly code.
____

This gem provides native Ruby support for the {htmx_link} JavaScript library so you can build sophisticated web applications using pure Hypermedia REST APIs while avoiding unnecessary bloat and complexity common with the JavaScript ecosystem. By building upon the original foundations of Hypermedia REST APIs, you can build rich web applications with no additional JavaScript!

At the moment, the functionality of this gem is still in the early stages of development but the goal of this gem is to aid with the development of {htmx_link} applications.

💡 This is used with the {hanamismith_link} gem when building {hanami_link} applications. Even better, you can play with the link:https://github.com/bkuhlmann/hemo[Hanami demo application] to learn more. Enjoy!

toc::[]

== Features

- Augments the {htmx_link} JavaScript library.
- Speeds up {htmx_link} development.
- Compatible with {hanami_link}, {roda_link}, and other web frameworks.

== Requirements

. A strong understanding of {hypermedia_systems_link}.
. {htmx_link}.
. link:https://www.ruby-lang.org[Ruby].

== Setup

To install _with_ security, run:

[source,bash]
----
# 💡 Skip this line if you already have the public certificate installed.
gem cert --add <(curl --compressed --location https://alchemists.io/gems.pem)
gem install htmx --trust-policy HighSecurity
----

To install _without_ security, run:

[source,bash]
----
gem install htmx
----

You can also add the gem directly to your project:

[source,bash]
----
bundle add htmx
----

Once the gem is installed, you only need to require it:

[source,ruby]
----
require "htmx"
----

== Usage

One of the first tasks you'll want to tackle, when working with the {htmx_link} library, is building HTMX specific HTML attributes. This can be accomplished by using the `.[]` method. For example, when implementing a {hanami_link} view part, you could use the following:

[source,ruby]
----
tag.button(
"Delete",
class: "button decline",
type: "submit",
**HTMX[target: "closest .task", delete: "/tasks/#{value.id}"]
)
----

The above would produce the following:

[source,html]
----

Delete

----

Notice the appropriate HTMX `hx-target` and `hx-delete` attributes are built which are compatible with the {htmx_link} library while not having to manually prefix each one of these attributes with the `hx-` prefix. You can even use symbols, strings, or a mix of both as well.

=== HTML Attribute Prefixes

As shown above, building HTMX attributes takes minimal effort but if you'd prefer the HTML `data-` prefix, which the {htmx_link} library supports, you can customize by using the following:

[source,ruby]
----
prefixer = HTMX::Prefixer.new "data-hx"

tag.button(
"Delete",
class: "button decline",
type: "submit",
**prefixer.call(target: "closest .task", delete: "/tasks/#{value.id}")
)
----

This would then produce the following HTML code:

[source,html]
----

Delete

----

As you can see, the `data-hx-target` and `data-hx-delete` keys are used. These are definitely more verbose than the `hx-` keys. By the way, the `HTMX::Prefixer` is called when using the HTMX `.[]` as shown earlier. This means the following are equivalent:

[source,ruby]
----
HTMX[delete: "/tasks/1"]
HTMX::Prefixer.new.call delete: "/tasks/1"
HTMX::Prefixer.new("hx").call delete: "/tasks/1"
----

All three of the above will produce the same output which means you'll most likely want to use the `.[]` method since it has the shortest syntax.

If you attempt to use an unsupported prefix, you'll get an error:

[source,ruby]
----
HTMX::Prefixer.new "bogus"
# Invalid prefix: "bogus". Use: "hx" or "data-hx". (HTMX::Error)
----

Some {htmx_link} attributes use dashes. For those situations, you can use strings for keys or underscored symbols to produce the correct HTMX syntax. Here's and example using both a string and symbol for keys:

[source,ruby]
----
HTMX["swap-oob" => true, push_url: "/demo/123"]
# {"hx-swap-oob"=>true, "hx-push-url"=>"/demo/123"}
----

=== HTTP Headers

When working with HTTP requests/responses, especially HTTP headers, there are a few objects that can parse and make the data easier to work with. These objects are named accordingly: request and response. Here's how to use them.

==== Request

The request object allows you to obtain a {data_link} object to interact with when parsing link:https://htmx.org/reference/#request_headers[HTMX HTTP request headers]. Example:

[source,ruby]
----
HTMX::Headers::Request.new

#
----

Notice you get a {data_link} instance where all members have the `HX-` prefix removed while each value defaults to `nil`. Even better -- and more practical -- is you can ask the request object to parse the incoming HTTP headers directly and give you _exactly_ what you need:

[source,ruby]
----
HTMX::Headers::Request.for request.env

#
----

With the above, the `.for` method plucks out only the HTMX specific headers which may or may not have values. Extra header keys, which are not specific to {htmx_link}, are ignored.

==== Response

The response object allows you to obtain a {data_link} object to interact with when parsing link:https://htmx.org/reference/#response_headers[HTMX HTTP response headers]. Example:

[source,ruby]
----
HTMX::Headers::Response.new

#
----

Notice you get a {data_link} instance where all members have the `HX-` prefix removed while each value defaults to `nil`. Even better -- and more practical -- is you can ask the response object to parse the incoming HTTP headers directly and give you _exactly_ what you need:

[source,ruby]
----
HTMX::Headers::Response.for response.headers

#
----

With the above, the `.for` method plucks out only the HTMX specific headers which may or may not have values. Extra header keys, which are not specific to {htmx_link}, are ignored.

=== Errors

As you've probably picked up by now, any/all errors issued by this gem will be an instance of the `HTMX::Error` class which inherits from `StandardError`. you can use this classification to catch and deal with these errors in your own implementation as desired.

== Development

To contribute, run:

[source,bash]
----
git clone https://github.com/bkuhlmann/htmx
cd htmx
bin/setup
----

You can also use the IRB console for direct access to all objects:

[source,bash]
----
bin/console
----

== Tests

To test, run:

[source,bash]
----
bin/rake
----

== link:https://alchemists.io/policies/license[License]

== link:https://alchemists.io/policies/security[Security]

== link:https://alchemists.io/policies/code_of_conduct[Code of Conduct]

== link:https://alchemists.io/policies/contributions[Contributions]

== link:https://alchemists.io/projects/htmx/versions[Versions]

== link:https://alchemists.io/community[Community]

== Credits

* Built with link:https://alchemists.io/projects/gemsmith[Gemsmith].
* Engineered by link:https://alchemists.io/team/brooke_kuhlmann[Brooke Kuhlmann].