• Parallel MongoRecord test execution with ScalaTest

    June 8, 2013

    A few weeks ago, I finally figured out a way to enable parallel test execution of Lift MongoRecords using ScalaTest. The problem is when you call MongoDB.defineDb the entry is added to a Map with the MongoIdentifier as the key. So, you can't add more than one entry for the same MongoIdentifer, which means you can't use a different database for testing without doing them one at a time.

    The solution is rather simple and involves Lift's Dependency Injection mechanism. It allows us to use a different MongoIdentifier for each test suite.

    First we need to define an injectable MongoIdentifier to add to our model's MongoMetaRecord. I put this in a MongoConfig object:


  • JavaScript Apps With Lift: Build Tools

    April 6, 2013

    Now that we know how to organize and write our JavaScript code, we need a way to build our single file for use in production. There are several ways you can do this.

    Scala Build Tool

    Most build tools have plugins for this, whether you're using SBT, Maven, or Gradle. I'm an SBT user, so I've been using sbt-closure and less-sbt. However, these are extremely slow, the SBT plugins, that is. I haven't used the other build tools. Also, it's not necessary to run google closure every time a change is made. This really only needs to be done once, when packaging for deployment.

    sbt-resource-management


  • JavaScript Apps With Lift: JsClass

    April 5, 2013

    The Lift Extras module adds some convenience classes to help with interfacing between your Scala snippet code and your JavaScript code.

    In my last post the code used to initialize the JavaScript code from within the snippet looked like this (minus the knockout binding call):

    val onload: JsCmd =
      SetExp(
        JsVar("window.koExample"),
        JsExtras.CallNew(
          "App.views.knockout.KnockoutExampleCls",
          JsExtras.AjaxCallbackAnonFunc(sendSucces),
          JsExtras.JsonCallbackAnonFunc(saveForm),
        )
      )
    )
    

    Elsewhere, there's a call to a function on the JavaScript class:

    Call("window.koExample.textInput", Str(""))
    

  • JavaScript Apps With Lift: Callback Functions

    April 4, 2013

    One of my favorite features of Lift is the ability to call functions on the server via ajax. This is mostly achieved using built in features. However, I also like to be able to call these functions via JavaScript directly. So, I created some functions to help with this.

    First, let's take a look at AjaxCallbackAnonFunc:

     object AjaxCallbackAnonFunc {
        def apply(callback: () => JsCmd): AnonFunc = {
          val funcCmd = S.fmapFunc(S.SFuncHolder(s => callback()))(name =>
            SHtml.makeAjaxCall(JsRaw("'" + name + "=true'"))
          )
          AnonFunc(funcCmd)
        }
      }
    

  • JavaScript Apps With Lift: Organization

    April 3, 2013

    With the goal of putting as much of our JavaScript code in external files and combing them into a single file, there are several ways to organize your code. A lot of developers are moving towards using an AMD loader, in particular RequireJS for webapps. With this, each of your JavaScript files will basically list the files it depends on and they are loaded by the loader. So, only the files you need are loaded. That's only recommended for development, though. For production, all of the files are combined using an optimizer.


  • JavaScript Apps With Lift: Best Practices

    April 2, 2013

    In this post I will discuss best practices for serving assets within the context of a Lift app. Google and Yahoo have both published extensive material on this, so I won't go over all of the details. I will just concentrate on the things directly related to developing webapps with Lift.

    Minimize HTTP Requests

    In general you should combine all of your JavaScript files into a single file. For landing pages there may be other things to consider.

    By default, Lift loads a couple of files dynamically.

    liftAjax.js: You can turn this off and load it statically. Firstly, load your site and save the file, then in Boot.scala add the following:


  • Dealing with Boxed values in Lift snippets

    March 26, 2013

    This post will demonstrate how to handle Box(ed) values in Lift snippets using for comprehensions. This is what a first attempt might look like:

    object MySnippet {
      object SomeRequestVar extends RequestVar[Box[String]](Full("nothing"))
      def render =
        for {
          myVar <- SomeRequestVar.is ?~ "MyVar is not defined"
          user <- User.currentUser ?~ "You must be logged in"
        } yield ({
          "#name" #> user.name.is
        }) match {
          case Full(csssel) => csssel
          case Failure(msg, _, _) => "*" #> <div class="error">{msg}</div>
          case Empty => "*" #> <div class="error">Empty</div>
        }
      }
    }
    

About

I'm Tim, a software developer. Currently focused on Scala, Lift, MongoDB, and JavaScript.

@eltimn
eltimn

Projects

Lift Mongoauth
Lift Extras
Lift-Mongo giter8 Template
jQuery Bootstrap Alerts
jQuery Bootstrap Form Alerts