Hello World, for more than English

If you read the getting started guide, you know that a "Hello World" Plezi application only needs just a few lines of code... it can be written using the irb terminal like so:

require 'plezi'
class Hello
   def index
      'Hello World!'
Plezi.route '*', Hello
exit # <- this exits the terminal and starts the server

So... instead of writing the shortest hello world tutorial, we're going to write a "realistic" (read: bloated) hello world example that will allow us to say "Hello world":

Create a starter application

Plezi provides us with a jump start, so that we can begin coding straight away and not spend time on creating folders and writing the same stuff over and over again.

Let's open our terminal window and type:

$ plezi new hello_world

You should get a response on your terminal, something along these lines:

created the hello_world application directory.
starting to write template data...

    wrote ./hello_world
    wrote ./hello_world.rb
    wrote ./routes.rb
    wrote ./config.ru
    wrote ./Procfile
    wrote ./Gemfile
    wrote ./rakefile
    created ./controllers
    wrote ./controllers/example.rb
    created ./views
    wrote ./views/assets
    wrote ./views/welcome.html.erb
    wrote ./views/404.html.erb
    wrote ./views/500.html.erb
    wrote ./views/503.html
    created ./public
    created ./public/javascripts
    wrote ./public/javascripts/client.js
    wrote ./public/javascripts/simple-client.js
    created ./test

please change directory into the app directory: cd hello_world

run the hello_world app using: ./hello_world or using the iodine or rackup commands.

Great. We have something to start with.

Here's the list of files that Plezi created for us. We can skip reading the list, but I'm putting it here so we can have a quick reference guide whenever we're wondering about this or that file:

Let's double click on the hello_world script file to start our application (or run ./hello_world from our terminal).

Next, let's open a new browser window or two and visit localhost:3000 to see what we've got. We can use two browser windows to chat with ourselves...

Congratulations! We've created a Plezi application. It's a chat room and we want it to be something different, but it's a start :-)

You can press CTRL+C in your terminal to stop the app server, or just close the shell window.

Parlez-vous fran├žais?

NOTE: The following information will be updated later to be consistent with the template app created by plezi new hello_world above, but it still serves to demonstrate how you can use params with Plezi's "Re-write Routes". Stay tuned!

Plezi created a Controller for us - located at controllers/example.rb - and a landing page template - located at views/welcome.html.erb.

We want these to say "Hello world" in three languages:

Since we know any String returned by a Controller is automatically appended to the Rack::Response (response) object, we can simply edit our Controller for each language. For example, we could do something like this:

class RootController
  # HTTP
  def index
    # any String returned will be appended to the response. We return a String.
    case params['locale']
    when 'it'
      "Ciao mondo"
    when 'fr'
      "Salut le monde"
      "Hello world"

Although this might work, it will be no fun when we want to support 52 languages...

...However, I also don't want to install the I18n gem right now. Sure, the I18n gem would probably be a great solution, but we're going to keep this translation code for now. We're here to learn how to use Plezi; we can always revisit this code later on.

Let's restart our application and visit:

This is okay but... well... it's ugly. The URL looks ugly and there's no HTML formatting... Let start with fixing that URL, shall we?

Rewriting the route

Plezi supports inline route parameters. So we could edit our routes.rb file to be something like this:

Plezi.route ':locale', RootController

But then we have to always use a locale, which is ugly in a different way and means the root path ('/') just became invalid... besides, when we have 15 routes, we will have to keep writing :locale every time, which is error-prone.

Rewrite routes give us so much more flexibility and control.

A rewrite route uses a Regexp object instead of a Controller and it will look something like this (let's write this into our routes.rb file):

Plezi.route ':locale', /^(en|fr|it)$/
Plezi.route '/', RootController

Let's restart our application and visit:

So what's happening here?

Hence: * A request to /something will be seen by RootController as /something with no params['locale']. * A request to /fr/something will be seen by RootController also as just /something but with params['locale'] now set to 'fr'.

Much better. Next step - let's fix use a template to render this in html format.

Using templates

To use templates, we will need to update our Controller one last time (this will be our final code for the hello_world controller).

We will save the message in a variable we can access later and we'll use the Controller#render function to render an html template (our view):

class RootController
  # HTTP
  def index
    # any String returned will be appended to the response. We return a String.
    @msg = case params['locale']
           when 'it'
             'Ciao mondo'
           when 'fr'
             'Salut le monde'
             'Hello world'
    render 'hello'

Now our application is broken, because we are calling render 'hello', but the 'hello' template doesn't exist.

We will need to save a file named 'views/hello.html.erb' in the views folder.

A few things about the file name (Plezi is a bit opinionated about it):

Here's what our simple 'views/hello.html.erb' file looks like:

<!DOCTYPE html>
<title><%= @msg %></title>
    <h1><%= @msg %></h1>

Cool, let's restart the application and see our work so far at:

Adding JSON

I promised three languages, so far so good.

But I also promised two output formats (html and JSON) using the same codebase for the controller... so how do we add JSON without changing our Controller's code?

Well, let's start with what we know. To control formatting we will want a :format parameter. We already know how to use rewrite routes.

Now our routes.rb file should look something like this:

Plezi.route ':format', /^(html|json)$/
Plezi.route ':locale', /^(en|fr|it)$/
Plezi.route '/', RootController

We also know how to write templates, so let's add a JSON template. The file will be called 'views/hello.json.erb' and it should look something like this:

<%= {message: @msg}.to_json %>

This is all we learned so far, so let see if that might be enough... let's restart the application try it:

Wow, that's it. It actually works automatically, since the :format parameter is a reserved parameter for template formatting. This allows us to use a single controller codebase for different formats without doing a thing.

As you can see, the html format and the en locale are both optional, since they are the application's default values.

But what would happen if we tried requesting a format that we didn't support (no template provided)?

Let's edit our routes.rb to find out:

Plezi.route ':format', /^(html|json|xml)$/
Plezi.route ':locale', /^(en|fr|it)$/
Plezi.route '/', RootController

Now, let's restart the application and try visiting localhost:3000/xml/fr.

Handling errors

We hit an error, a missing page... it might be okay, but I do think that our xml request should get the error response as an xml document.

Let's create a file (a view / template will go in our views folder) named 'views/404.xml.erb' with the following:

<?xml version="1.0" encoding="UTF-8"?>
  <text>Not Found</text>
  <url><%= ::ERB::Util.h request.path_info %></url>

Now let's try this again: localhost:3000/xml/fr.

You might notice that the 404 error points at an empty request path (/ instead of /xml/fr) - this is why we call them rewrite routes.

Further exploration

There is much we didn't explore, such as; setting cookies using the cookie['name'] = "value", redirection (hint: redirect_to) and other cool tidbits. But we have enough to point us in the right direction.

I found, for myself, I learn best by simply doing, so I invite you to simply jump in the water.

On the other hand, if you're prefer reading some more, pick any of the Plezi guides and enjoy.