Programming
comments 10

Web Application Development with Clojure – Part 3

This post is part of the Web Application Development with Clojure tutorial. You might want to read the previous posts before this post for continuity’s sake.

Introduction

In the previous part of this tutorial we created a couple of tables using migrations – authors table and posts table. In this part first I’ll describe how to load some test data (a.k.a ‘fixtures‘) into our database tables. We’ll use YAML to define a couple of authors and 3 blog posts and we’ll parse the YAML file and load the data using the clj-yaml library.

Also we’ll create our first template and render the blog’s home page with the sample data from the database.

Source code on github

The code for this series is now available on github and the source code is tagged with part names. If you want to checkout the code for a specific part of this tutorial you can do so using the following command:

A quick note for PostgreSQL users: In the previous while creating the tables using migrations, I overlooked and made a mistake in naming the tables. If you are using PostgreSQL then the word “user” is a reserved word, so you should rename the table to authors – I’ve updated the code accordingly.

Loading Fixtures

Fixtures are used to populate the database with some initial data. Though fixtures are mostly used for loading test data we can also use fixtures to bootstrap the content. First let us create a file called fixtures.yml under resources folder. If you don’t have a resources folder in your project, create it under the root directory so that will be at the same level as src folder. Edit the fixtures.yml and add the following:

Pay attention to the formatting of the text in a YAML file, otherwise you might get exceptions during parsing.

Check out part 1, if you want to refresh your memory on how to setup IntelliJ IDE

Now, fire up the Clojure REPL in IntelliJ IDE using Tools -> Start Clojure Console. We’ll load the clj-yaml library and parse the yaml file.

If everything went well, you should see the map with keys :authors and :posts in the console as shown below:

Now to add the authors to the database all you need is the following couple of lines:

As you can see, you don’t need to write the code in a file, compile, redeploy and refresh to modify your program. All you need is a REPL which you use to build your program bottom-up – one little function at a time.

The second line in the above code snippet reads the fixtures file using slurp, parses the yaml using parse-string which returns a map with keys :authors and :posts. We use clojure’s maps-as-functions-of-keys features to get the list of authors and pass them to Korma’s insert function. Once this is executed you can see the data is now inserted into the Users table.

In a real-world-application you never use password, but instead you will probably store some encrypted hash. I’ll leave that as an exercise to the reader (not the clojure reader!).

Templates using Enlive

Now that we have our sample data populated in the database, it is time to get started with our first template. Clojure has a couple of libraries that can help you with dealing with HTML viz, Hiccup and Enlive. Hiccup is a DSL for generating HTML and Enlive is a selector based templating engine. I’m a bit biased towards Enlive – since I have more freedom of styling and HTML stays HTML. So in this tutorial I’m using Enlive.

Defining Home Page Template

Enlive provides a macro called deftemplate to define template functions. The macro is defined as follows:

The forms you pass in are actually used to transform the html. I think it will be easier to understand with an example that you can follow along. First let us create the home.html under resources folder. By convention the templates are loaded from the resources directory.

We will place all our template definitions in clog.templates namespace which lives in cleverly named templates.clj

In the above snippet we are using deftemplate macro to create a template function called home-page which takes the file home.html and transforms the file using the forms, in our case only one which is:

This says find out the tag :title in the home.html and replace its contents with “Clog – the clojure blog engine!”. To test this out you can load the namespace in repl and run the home-page function. That will print out the transformed template as shown below.

Now this template function can be used to generate the transformed html we need to send to the client. To connect the these views to the requests, we will use simple controller functions. These functions/handlers are then used to transform the templates using the request parameter and data from the database. For example we want our blog to respond to something like http://host:port/posts/1 by sending out the html for the post with id 1. This logic is wrapped inside a controller function.

A simple Controller

We’ll put our controller functions in the clog.controller namespace. Here’s the initial version of the controller which has handler for the index page.

Now to see this function in action, we need to update the routes of the application in core.clj to call clog.controller/index. Here’s the complete core.clj after the required modifications:

Notice that delegate call in routes ? This is due to small gotcha in mustache route syntax. We can’t use the function directly as the handler, since we want the parameters of the handler, in our case ‘req’ to be passed to function. So we use delegate to pass the request as the first argument.

Start the server as shown below, and you should see the home page with title in the window title bar “Clog – the clojure blog engine!”.

List of Posts

The home is working, but it is rather boring and doesn’t show any real data. Let us try to show the two posts we added in the database. First we need to update the home.html to create a place holder for a post.

Now let us update the template and add another transformation. In this case we want to “clone” the div with class post and replace the content of divs with classes title and content. Here’s the updated deftemplate’s code that does exactly the same. We are using clone-for macro and using the forms to transform the sub elements.

Now we need to make sure that our controller function sends the required data to the template.

We are selecting all the posts using Korma select function and passing it on to home-page function. The result of the home-page template function – which is the html with posts populated is passed on to response.

After making these changes, you should see the list of posts in the home page.

Don’t worry about styling of the page, we’ll add a pretty CSS in the next part of the tutorial.

Conclusion

In this part we saw how to glue things together and get the content from database, render it in a page using templates. In the next part we’ll finish by updating the home template and adding another template to display the post. Also, in the next part we’ll start working in creating an admin area with authentication.

Make sure you subscribe to the RSS feed or follow me on Twitter to get notified.

10 Comments

  1. Pingback: VijayKiran.com – Web Application Development with Clojure – Part 2

  2. Elmany says

    Hi,
    first thanks for these wonderful posts I think that there isn’t any like this about clojure outhere. Really a lot of thanks.

    Now, I think I’m missing something:
    when I use:
    (select authors)
    I can see the list of authors

    but with (select posts)
    I get []

    So I thought that I needed to insert the post in the same way of the authors like:
    (insert posts (values (:posts (parse-string (slurp “./resources/fixtures.yml”)
    But I got a Failure to execute query

    Sorry for my dumbness :-(

    I changed the authors id to 2 and 3 in authors and posts inside the yaml to preserve the first post added in  part 2.

    Can you help me with this?

  3. Elmany says

    Hi again,

    Once more one thousand thanks for these series! thanks to you now I’m getting how all things connect in the clojure world.
    I was really missing the part of insert the posts like I said in my previous post:

    (A) (insert posts (values (:posts (parse-string (slurp “./resources/fixtures.yml”)

    I was getting the “Failure to execute query” because two things:
    1.- In the yaml file the field text: is not correct because we defined the text of the post as “content” in our migration file.
    So I replace the “text” field in the yaml file for “content”
    Once that’s fixed. I run the statement (A) again and got this error:
    null value in column “id” violates not-null constraint
    So
    2.- I went back to the yaml file and added the id field

    Then running (A) again
    (use ‘clog.core)
    (start 9000)
    and Tha-da!

    Everything was fantastic again!!!

    PS: I (rollback) the database first so that I could start fresh.

    • Hi Elmany,

      Sorry, I’m traveling this week and have very limited access to the internet. I’m glad you sorted out the problem :-)

      • Elmany says

        Once again thanks to you. You don’t know how many tutorials I’ve follow trying to grasp all the moving parts of Clojure without any success. I can tell that this is the first of many where everything is explained in a way that if something is wrong, you already have the idea of how to solve it by yourself, like in my case.
        I haven’t been able to finish it until part 5 because “external factors” but, I wan to know if you can write a little bit about what’s needed to deploy to a home server, what is needed if for example if using apache, or ngnix.
        I know you plan to make a post about deploying to services like heroku and I think that they make a grate work and maybe it is death simple, but if you could talk about these it could be also good.

        Thanks

        Many

  4. Pingback: VijayKiran.com – Web Application Development with Clojure – Part 1

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">