Essential Guide 1: Setup

Demo: Matestack Demo Github Repo: Matestack Demo Application

Welcome to the first part of our tutorial about building a web application with matestack.

Introduction

In this guide, we will

  • create a new Rails application

  • install matestack-ui-core

  • create and render our first 'Hello world' page

  • add a simple matestack app, wrap our page and add another one

Prerequisites

To follow along, make sure you have successfully installed

Getting started

In the terminal, create a new Rails app by running

rails new matestack-demo-application --skip-turbolinks

We skip turbolinks, because matestack has it's own loading api which makes turbolinks unnecessary. Using turbolinks in a matestack application can result in unwanted behavior and errors.

Remove turbolinks if installed We encourage you to remove turbolinks if it's installed. To do so remove the line gem 'turbolinks', '~> 5' from your Gemfile and remove require("turbolinks").start() from the app/javascript/packs/application.js file. To clean things up remove the two "data-turbolinks-track": "reload" key/value pairs from your app/views/application.html.erb. </details>

Switch into the newly created project via

cd matestack-demo-application

Need to create database first

rake db:create

To make sure things work as expected, you can run

rails s

to start the application. Now visit localhost:3000 and you should see the canonical Yay! You're on Rails! screen!

Install Matestack

To install matestack, run gem install matestack-ui-core or add gem 'matestack-ui-core' to your Gemfile and run bundle install.

For a complete setup with Webpacker, you also need to run yarn add https://github.com/matestack/matestack-ui-core#v1.3.2 followed by yarn install.

Then, add

import MatestackUiCore from 'matestack-ui-core'

to the app/javascripts/packs/application.js and run

bin/webpack

to compile your JavaScript code.

In order to use matestack complete the setup by including the Matestack::Ui::Core::ApplicationHelper in your ApplicationController. Your app/controllers/application_controller.rb should look like this:

class ApplicationController < ActionController::Base
  include Matestack::Ui::Core::ApplicationHelper
end

And add an element with the id matestack_ui to your layout, by changing your app/views/layouts/application.html.erb. It should look like this:

<!DOCTYPE html>
<html>
  <head>
    <title>MatestackDemoApplication</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all' %>
    <%= javascript_pack_tag 'application' %>
  </head>

  <body>
    <div id="matestack-ui">
      <%= yield %>
    </div>
  </body>
</html>

By including the Matestack::Ui::Core::ApplicationHelper and defining a div with the matestack-ui id you can now use matestacks render method in your controller actions. Based on the id matestack apps and pages can be rendered and pages can be replaced without a full reload of the browser page.

Create our first page

Apps, Pages and Components will live in a Matestack directory inside your app directory. So lets create a directory called matestack inside app.

Now lets create our first page featuring the well known "Hello World!" greeting.

Before creating our page we add a root route which calls the first_page action of our DemoController. Change your config/routes.rb and add the following route.

Rails.application.routes.draw do
  root to: 'demo#first_page'
  get '/first_page', to: 'demo#first_page'
end

Accordingly to our route we create a new controller called demo_controller.rb within app/controllers/.

class DemoController < ApplicationController

  def first_page
    # later we will render our page here
  end

end

Now its time to create our first page. Create a file called first_page.rb in app/matestack/ and add the following content. We will take a closer look at what is happening down below.

class FirstPage < Matestack::Ui::Page

  def response
    div do
      heading text: 'Hello World!', size: 1
    end
  end

end

A page needs to inherit from Matestack::Ui::Page. Each page must have a response method. The response method should contain your html (written in ruby) which will be displayed when this page gets rendered.

In our FirstPage we define the response method and inside call div with a block and heading with text and size inside this block. div and heading are two of many Matestack::Ui::Components which you can use to create UI's in Ruby. As you might can imagine the div call will render a <div></div> and the given block will be rendered inside this div. heading renders a html headline tag with the given size, in this case a h1 tag. So this response message would look like this in HTML:

<div>
  <h1>Hello World!</h1>
</div>

Okay, so now lets render this page and take a look at it in the browser.

To render a page matestack provides a render helper through the module you included earlier in the ApplicationController.

Rendering the page is as simple as calling render FirstPage. Change your DemoController to look like this.

class DemoController < ApplicationController

  def first_page
    render FirstPage
  end

end

We successfully rendered our first page displaying "Hello World" without writing any HTML code.

Create our first app

Lets say we want to add a header with navigation links to our first page and upcoming pages. In Rails we would implement this navigation inside our layout, so we don't repeat ourselfs by adding the navigation in every single view. With Matestack we have so called apps which replace the concept of Rails layouts. In order to add a navigation around our page similiar to a rails layout we will create an app called Demo::App. But where to put this app. We recommend you structure your apps and pages as follows:

In our example we want to have a demo app and pages rendered inside this app. That means that Demo is our namespace for those. Therefore we put our app and pages inside a folder called demo. We move our first page inside this demo folder because it should belong to the demo app. Since we can have many different pages we put all pages in a subfolder called pages.

app/matestack/
|
└───demo/
│   │   app.rb (`Demo::App`)
│   └───pages/
│   │   │   first_page.rb  (`Demo::Pages::FirstPage`)

Because we moved our first page inside demo/pages we need to update the class name accordingly, matching the Rails naming conventions. Update the class name of your first page to Demo::Pages::FirstPage.

Now we create the demo app by creating a file called app.rb inside app/matestack/demo and add the following content. We will take a closer look at what is happening down below.

class Demo::App < Matestack::Ui::App

  def response
    header do
      heading size: 1, text: 'Demo App'
    end
    main do
      yield_page
    end
  end

end

What is happening here. An app needs to inherit from Matestack::Ui::App and define a response method like a page. header, heading, main are all matestack component helper like div which we used in our first page. The yield_page call tells the app where the page content should be rendered. In this case inside a main tag beneath the header tag.

The last thing we need to do in order to render our app around our page is to tell the controller to use the app as a layout. We do this by adding matestack_app Demo::App inside our controller, which should now look like this:

class DemoController < ApplicationController
  matestack_app Demo::App

  def first_page
    render FirstPage
  end

end

If we visit localhost:3000 now, we can see that our app is rendered around our first page and the "Hello world!" is shown below the heading "Demo App".

Create a second page

In order to better unterstand which advantages and features apps provide, let's create a second page.

First we add a route to our routes.rb file.

Rails.application.routes.draw do
  root to: 'demo#first_page'
  get '/second_page' to: 'demo#second_page'
end

Afterwards we create the second page under app/matestack/demo/pages as second_page.rb and add some page content.

class Demo::Pages::SecondPage < Matestack::Ui::Page

  def response
    div do
      heading size: 1, text: 'I am the second page!'
      paragraph text: "I'm a paragraph on the second page."
    end
  end

end

To view our second page we need to add the corresponding controller action second_page.

class DemoController < ApplicationController
  #...

  def second_page
    render Demo::Pages::SecondPage
  end

end

Visit localhost:3000/second_page to view our second page.

Understanding matestack apps

Now we have two pages which we can only visit via typing in the url. Let's add a navigation above our header to our app in order to navigate between these two pages. We do this like we would normally do it, by adding two links into a nav html tag using matestacks link helper. In this step we also add a footer for better understanding of whats happening later.

class Demo::App < Matestack::Ui::App

  def response
    nav do
      link path: root_path, text: 'First Page'
      link path: second_page_path, text: 'Second Page'
    end
    header do
      heading size: 1, text: 'Demo App'
    end
    main do
      yield_page
    end
    footer do
      hr
      small text: 'These guides are provided by matestack'
    end
  end

end

As you might guess right now, all the method calls like nav, footer, hr, small are calls of matestack helpers representing the equivalent html tags.

If we visit localhost:3000 now, we see our page with the 'Hello World!' content wrapped by our navigation, header and footer. Clicking the link to the second page, the whole browser page is rerendered and we see our second page. Nothing special here, but matestack provides us with a transition helper. Let's take a look at what it does by changing our links to transitions.

class Demo::App < Matestack::Ui::App

  def response
    nav do
      transition path: root_path, text: 'First Page'
      transition path: second_page_path, text: 'Second Page'
    header do
      heading size: 1, text: 'Demo App'
    end
    main do
      yield_page
    end
    footer do
      hr
      small text: 'These guides are provided by matestack'
    end
  end

end

Again visit localhost:3000. Okay now pay close attention to the navigation, header and footer from our app. When you click one of the links generated by the transition helper, you should notice that only the page content, in this case the 'Hello World!' gets replaced by the contents of our second page.

matestack transitions asynchronously fetch the requested page without the app layout and only replaces the page. Providing a more app like or SPA like behavior. And all you needed to do was creating an app for your pages.

Commiting the status quo

Let's save the progress so far using Git. In the repo root, run

git add . && git commit -m "Save basic Rails app with PG and matestack set up"

to do that.

Recap & outlook

We now have a working Rails app using matestack.

In this guide we learned how matestack pages work, how we can use matestacks components to create html and how we can use an app as a layout for pages and what benefits we get through using an app.

After taking a well deserved rest, make sure to continue exploring the features matestack offers you by checking out the next part of the series.

Last updated