Using Raxx.View in Plug applications

There are several articles explaining the value of creating applications with just Plug, when you don't require all the trappings of a batteries included framework. One common example is a small API service.

What happens though when your simple application requires a single dashboard page? Or for some other reason you want to show a bit of HTML? This is where Raxx.View comes in.

Raxx is a web toolkit. It consists of a simple interface and a selection of powerful yet focused libraries. Each one is built to ease a particular element of developing web applications. Raxx.View is one of these libraries and, despite the name, is just as useful in a Plug application.

Not interested in piecing together your own framework? Try Raxx.Kit which makes starting a new project as simple as two commands:


        $ mix archive.install hex raxx_kit
        $ mix raxx.kit my_app
      
Now, back to those Plug applications.

Defining views

Below is the example taken from the Raxx.View documentation.


      defmodule MyApp.ListUsers do
        use Raxx.View,
          arguments: [:users, :title],
          template: "list_users.html.eex",
          layout: "layout.html.eex"
      end
    

This is a simple example and the library has support generating helpers, partials and layouts. It also helps with reusing any of these components across multiple views. For full details see the documentation.

Rendering views

Using Raxx.View in the module above generated a html/2 function. This function takes users as the first argument and a title as the second.

The module MyApp.ListUsers is now a view. Let's add the callbacks required to make it a Plug as well.


      defmodule MyApp.ListUsers do
        import Plug.Conn

        use Raxx.View,
          arguments: [:users, :title],
          template: "list_users.html.eex",
          layout: "layout.html.eex"

        def init(options) do
          options
        end

        def call(conn, _opts) do
          users = [] # need to fetch users somehow
          title = "Users Admin"

          conn
          |> put_resp_content_type("text/html")
          |> send_resp(200, html(users, title))
        end
      end
    

It is also possible to keep the view and controller as separate modules.


      defmodule MyApp.ListUsersView do
        use Raxx.View, arguments: [:users, :title], # ... rest
      end

      defmodule MyApp.ListUsersController do
        # ... rest
        def call(conn, _opts) do
          users = [] # need to fetch users somehow
          title = "Users Admin"

          conn
          |> put_resp_content_type("text/html")
          |> send_resp(200, MyApp.ListUsersView.html(users, title))
        end
      end
    

And that's everything, which demonstrates that bringing together these two libraries is simple. It also enables a nice third way between a full framework like Phoenix and rolling your own on top of Plug.

A web toolkit?

In my opinion this is a nice example of a focused library being reusable. Perhaps unsurprisingly Raxx.View works as well in a Raxx application as it does in a Plug one, maybe even a Phoenix one but I am yet to try that.

In the process of building several web tools it has become obvious that many of these tools can be agnostic to the users' framework choices. So far there is BasicAuthentication and CORS. If you want to help develop these, or are starting your own part of the web toolkit, I'm always keen to hear about it. Get in touch via twitter or slack