Search code examples
haskellhaskell-snap-framework

Where do I put my snaplets?


I'm new to Haskell and Snap and I want to write a simple bug-tracking application. I set up a Snap project using $ snap init and it works. The problem is that I don't know how to go any further.

I want to create a snaplet Tickets that uses a database to store bug reports, and use that snaplet in my main web application.

I read the documentation about snaplets but I couldn't figure out where to put their source code (in the /snaplets directory, I suppose? If so, how do I load them?). Could anybody point me in the right direction?


Solution

  • Are you sure you need to create a separate snaplet for Tickets? The snaplet infrasructure is meant for reusable components such as session management, authentication, database access, admin panels, user management, etc.

    Are you going to be using your Tickets self-contained module across multiple web applications? If so, then by all means go ahead and create a snaplet.

    In any case, it sounds to me like you are at least in part asking how to organize a project with multiple "modules" or "parts" while using snap. I'll try to address this below. Please let me know if you feel I have missed the mark.

    Assuming you don't need to create a separate snaplet for Tickets:

    For functionality specific to a single site, I think you would be better off creating a few modules and developing the code for the functionality right inside your current application's package and module hierarchy. Here are a few points on how I have been organizing my snap projects of late:

    • I put my database-related code under modules in MyApp.DB. namespace. You could have a MyApp.DB.Tickets that contains all database calls needed for operation on your Tickets module.

    • I put all UI-related functionality under MyApp.UI. namespace. You could put a MyApp.UI.Tickets module that contains your Handlers, your Splices, your Forms and so on.

    • To handle forms, I use the excellent digestive-functors library. You may find this blog post helpful if you don't know them already.

    • I usually have a shared UI helper library under MyApp.UI.Helpers where I place common code used across all/most UI modules.

    • I usually have a shared Form helper library under MyApp.UI.Forms

    • Any code tangential to the fact that my application exposes a Web UI goes outside the MyApp.UI. namespace. So if my application needs to perform some offline analyses, I may put them under the MyApp.Analysis. namespace.

    Once you define and export your Handlers under MyApp.UI.Tickets, you can go to your Site.hs file and wire them into your application at specific routes.

    For inspiration on how to handle database connections, you can check out the postgresql-simple snaplet.

    However, if you do need to create a snaplet:

    A snaplet is simply a stand-alone application that uses the Snap.Snaplet infrastructure, (typically) has its own .cabal file and (typically) is its own Haskell package. Snap then gives you a way to embed or nest this re-usable, self-contained application in yet another snap application. Think a hierarchy of Russian dolls.

    Assuming you performed something similar to what I described in the section above, you are now 95% ready to convert to a snaplet. Just name your application snaplet-tickets, expose a SnapletInit using makeSnaplet and use nestSnaplet in another snap application to include this reusable piece of functionality right there.