Improve this page

Buffalo Documentation

github.com/gobuffalo/buffalo

GoDoc Build Status Code coverage status Go Report Card

Package buffalo is a Go web development eco-system, designed to make your life easier.

Buffalo helps you to generate a web project that already has everything from front-end (JavaScript, SCSS, etc.) to back-end (database, routing, etc.) already hooked up and ready to run. From there it provides easy APIs to build your web application quickly in Go.

Buffalo isn't just a framework, it's a holistic web development environment and project structure that lets developers get straight to the business of, well, building their business.

github.com/gobuffalo/buffalo-auth

GoDoc Build Status Code coverage status Go Report Card

$ go get -u github.com/gobuffalo/buffalo-auth

To generate a basic username / password authentication you can run:

$ buffalo generate auth

This will do:

  • Generate User authentication actions in actions/auth.go:

    • AuthNew
    • AuthCreate
    • AuthDestroy
  • Generate User signup actions in actions/users.go:

    • UsersNew
    • UsersCreate
  • Generate User model and migration ( model will be in models/user.go):

  • Generate Auth Middlewares

    • SetCurrentUser
    • Authorize
  • Add actions and middlewares in app.go:

    • [GET] /users/new -> UsersNew
    • [POST] /users -> UsersCreate
    • [GET] /signin -> AuthNew
    • [POST] /signin -> AuthCreate
    • [DELETE] /signout -> AuthDestroy
  • Use middlewares for all your actions and skip

    • HomeHandler
    • UsersNew
    • UsersCreate
    • AuthNew
    • AuthCreate

Sometimes you would want to add extra fields to the user model, to do so, you can pass those to the auth command and use the pop notation for those fields, for example:

$ buffalo auth first_name last_name phone_number notes:text

Will generate a User model (inside models/user.go) that looks like:

type User struct {
  ID                   uuid.UUID `json:"id" db:"id"`
  CreatedAt            time.Time `json:"created_at" db:"created_at"`
  UpdatedAt            time.Time `json:"updated_at" db:"updated_at"`
  Email                string    `json:"email" db:"email"`
  PasswordHash         string    `json:"password_hash" db:"password_hash"`
  FirstName            string    `json:"first_name" db:"first_name"`
  LastName             string    `json:"last_name" db:"last_name"`
  Notes                string    `json:"notes" db:"notes"`
  Password             string    `json:"-" db:"-"`
  PasswordConfirmation string    `json:"-" db:"-"`
}

github.com/gobuffalo/buffalo-goth

GoDoc Build Status Code coverage status Go Report Card

In Buffalo v0.9.4 the built in generator for github.com/markbates/goth was removed in favor of this plugin.

$ go get -u github.com/gobuffalo/buffalo-goth

Generate Users, Routes

$ buffalo generate goth-auth facebook twitter linkedin etc...

Generate Routes only

$ buffalo generate goth facebook twitter linkedin etc...

For more detailed usage visit https://gobuffalo.io/docs/generators#goth.

github.com/gobuffalo/buffalo-heroku

GoDoc Build Status Code coverage status Go Report Card

This is a plugin for https://gobuffalo.io that makes working with Heroku easier.

It assumes you are using Docker to deploy to Heroku. It is recommended you read https://devcenter.heroku.com/articles/container-registry-and-runtime first.

$ go get -u -v github.com/gobuffalo/buffalo-heroku
$ buffalo heroku --help

The buffalo heroku new command will setup and create a new Heroku app for you, with a bunch of defaults that I find nice.

There are a lot of flags and options you can use to tweak the Heroku app you create. Use the --help flag to see a list of them all.

$ buffalo heroku new -h

creates a new heroku application

Usage:
  buffalo-heroku heroku new [flags]

Flags:
      --addon:heroku-postgresql string   options: hobby-dev, hobby-basic, standard-0 (default "hobby-dev")
      --addon:heroku-redis string        options: hobby-dev (default "hobby-dev")
      --addon:sendgrid string            options: starter (default "starter")
  -a, --app-name string                  the name of the heroku app to deploy
      --auth                             log into heroku from the cli
  -d, --dry-run                          run the generator without creating files or running commands
  -l, --dyno-level string                free, hobby, standard-1x, standard-2x (default "free")
  -e, --environment string               the environment to run the application in (default "production")
  -h, --help                             help for new

The initial setup command will do a deploy at the end, but after that you'll want to use the buffalo heroku deploy command to push a new version of your application, it'll even try to run your migrations for you.

$ buffalo heroku deploy

github.com/gobuffalo/buffalo-plugins

GoDoc Build Status Code coverage status Go Report Card

A plugin for working with Buffalo plugins.

$ go get -u -v github.com/gobuffalo/buffalo-plugins
$ buffalo generate plugin --help
$ buffalo plugins list

buffalo plugins install pkg pkg pkg... buffalo plugins remove pkg pkg pkg...

Plugins can be configured via the ./config/buffalo-plugins.toml file that acts as the official list of plugins the application depends on. This is file is optional, until using the install and remove commands.

With no config file the output of buffalo plugins list and plugins.List() does not change. Once a configuration file is in place, then that file will dictate the output of those commands.

$ buffalo plugins list

Bin              |Command                    |Description
---              |---                        |---
buffalo-auth     |buffalo generate auth      |Generates a full auth implementation
buffalo-pop      |buffalo db                 |[DEPRECATED] please use `buffalo pop` instead.
buffalo-goth     |buffalo generate goth-auth |Generates a full auth implementation use Goth
buffalo-goth     |buffalo generate goth      |generates a actions/auth.go file configured to the specified providers.
buffalo-heroku   |buffalo heroku             |helps with heroku setup and deployment for buffalo applications
buffalo-pop      |buffalo destroy model      |Destroys model files.
buffalo-plugins  |buffalo generate plugin    |generates a new buffalo plugin
buffalo-plugins  |buffalo plugins            |tools for working with buffalo plugins
buffalo-pop      |buffalo pop                |A tasty treat for all your database needs
buffalo-trash    |buffalo trash              |destroys and recreates a buffalo app
buffalo-upgradex |buffalo upgradex           |updates Buffalo and/or Pop/Soda as well as your app

To add support for the plugin manager, one can either manually edit ./config/buffalo-plugins.toml or let buffalo plugins install create it for you.

$ buffalo plugins install

go get github.com/gobuffalo/buffalo-pop
./config/buffalo-plugins.toml
$ cat ./config/buffalo-plugins.toml

[[plugin]]
  binary = "buffalo-pop"
  go_get = "github.com/gobuffalo/buffalo-pop"
$ buffalo plugins list

Bin         |Command               |Description
---         |---                   |---
buffalo-pop |buffalo db            |[DEPRECATED] please use `buffalo pop` instead.
buffalo-pop |buffalo destroy model |Destroys model files.
buffalo-pop |buffalo pop           |A tasty treat for all your database needs

The buffalo-pop plugin was automatically added because the application in this example is a Buffalo application that uses Pop.

New plugins can be install in bulk with the install command

$ buffalo plugins install github.com/markbates/buffalo-trash github.com/gobuffalo/buffalo-heroku

go get github.com/gobuffalo/buffalo-heroku
go get github.com/gobuffalo/buffalo-pop
go get github.com/markbates/buffalo-trash
./config/buffalo-plugins.toml
$ buffalo plugins list

Bin            |Command               |Description
---            |---                   |---
buffalo-pop    |buffalo db            |[DEPRECATED] please use `buffalo pop` instead.
buffalo-heroku |buffalo heroku        |helps with heroku setup and deployment for buffalo applications
buffalo-pop    |buffalo destroy model |Destroys model files.
buffalo-pop    |buffalo pop           |A tasty treat for all your database needs
buffalo-trash  |buffalo trash         |destroys and recreates a buffalo app
$ cat ./config/buffalo-plugins.toml

[[plugin]]
  binary = "buffalo-heroku"
  go_get = "github.com/gobuffalo/buffalo-heroku"

[[plugin]]
  binary = "buffalo-pop"
  go_get = "github.com/gobuffalo/buffalo-pop"

[[plugin]]
  binary = "buffalo-trash"
  go_get = "github.com/markbates/buffalo-trash"

Finally plugins can be removed with the remove command. This only removes them from the config file, not from the users system.

$ buffalo plugins remove github.com/gobuffalo/buffalo-heroku

./config/buffalo-plugins.toml
$ cat ./config/buffalo-plugins.toml

[[plugin]]
  binary = "buffalo-pop"
  go_get = "github.com/gobuffalo/buffalo-pop"

[[plugin]]
  binary = "buffalo-trash"
  go_get = "github.com/markbates/buffalo-trash"
$ buffalo plugins list

Bin           |Command               |Description
---           |---                   |---
buffalo-pop   |buffalo db            |[DEPRECATED] please use `buffalo pop` instead.
buffalo-pop   |buffalo destroy model |Destroys model files.
buffalo-pop   |buffalo pop           |A tasty treat for all your database needs
buffalo-trash |buffalo trash         |destroys and recreates a buffalo app

In Buffalo v0.13.1-beta.1 events are now emitted with the buffalo setup command. The buffalo-plugins command will listen for this event and install the necessary plugins for an application. When completed it will emit the plugins.EvtSetupFinished event. This event should be listened to by other plugins to run their setup commands.

github.com/gobuffalo/buffalo-pop

GoDoc Build Status Code coverage status Go Report Card

This is the home for all things that combine Buffalo and Pop.

$ go get -u -v github.com/gobuffalo/buffalo-pop

The popmw.Transaction will wrap each request inside of a new database transaction and automatically commit, or rollback, based on whether or not an error was returned from an upstream buffalo.Handler or buffalo.MiddlewareFunc.

First you need to add the middleware to your application giving it access to your *pop.Connection, typically found at models.DB.

import "github.com/gobuffalo/buffalo-pop/pop/popmw"

func App() *buffalo.App {
  // ...
  app.Use(popmw.Transaction(models.DB))
  // ...
}

Once added to the middleware stack for your application you can then use this transaction in upstream middleware or handlers.

func MyHandler(c buffalo.Context) error {
  // Get the DB connection from the context
  tx, ok := c.Value("tx").(*pop.Connection)
  if !ok {
    return errors.WithStack(errors.New("no transaction found"))
  }
}

WARNING: DO NOT OPEN MULTIPLE TRANSACTIONS WITHIN EACH OTHER - doing so will cause many, many, many problems.

github.com/gobuffalo/envy

GoDoc Build Status Code coverage status Go Report Card

package envy makes working with ENV variables in Go trivial.

  • Get ENV variables with default values.
  • Set ENV variables safely without affecting the underlying system.
  • Temporarily change ENV vars; useful for testing.
  • Map all of the key/values in the ENV.
  • Loads .env files (by using godotenv)
  • More!

github.com/gobuffalo/events

GoDoc Build Status Code coverage status Go Report Card

Note: This package was first introduced to Buffalo in this PR. Assuming the PR is merged Buffalo will not start emitting events until v0.13.0-beta.2 or greater.

A list of known emitted events can be found at https://godoc.org/github.com/gobuffalo/events#pkg-constants

$ go get -u -v github.com/gobuffalo/events

To listen for events you need to register an events#Listener function first.

func init() {
  // if you want to give your listener a nice name to identify itself
  events.NamedListen("my-listener", func(e events.Event) {
    fmt.Println("### e ->", e)
  })

  // if you don't care about identifying your listener
  events.Listen(func(e events.Event) {
    fmt.Println("### e ->", e)
  })
}
events.Emit(events.Event{
  Kind:    "my-event",
  Message: // optional message,
  Payload: // optional payload,
  Error:   // optional error,
})

There is only one required field when emitting an event, Kind.

The Kind field is key to how people will interpret your messages, and should be constructed as such: <namespace>:<event-kind>:<err-optional>.

In the examples below from Buffalo you can see it is using the buffalo: name space for its events.

// EvtAppStart is emitted when buffalo.App#Serve is called
EvtAppStart = "buffalo:app:start"
// EvtAppStartErr is emitted when an error occurs calling buffalo.App#Serve
EvtAppStartErr = "buffalo:app:start:err"
// EvtAppStop is emitted when buffalo.App#Stop is called
EvtAppStop = "buffalo:app:stop"
// EvtAppStopErr is emitted when an error occurs calling buffalo.App#Stop
EvtAppStopErr = "buffalo:app:stop:err"

By default events implements a basic manager for you. Should you want to replace that with your own implementation, perhaps that's backed by a proper message queue, you can implement the events#Manager interface.

var _ events.Manager = MyManager{}
events.SetManager(MyManager{})

Once Buffalo is actively emitting events, plugins, will be able to listen those events via their CLIs.

To do so you can set the BuffaloCommand to events when telling Buffalo which plugin in commands are available. Buffalo will create a new listener that says the JSON version of the event to that command in question.

var availableCmd = &cobra.Command{
	Use:   "available",
	Short: "a list of available buffalo plugins",
	RunE: func(cmd *cobra.Command, args []string) error {
		plugs := plugins.Commands{
			{Name: "echo", UseCommand: "echo", BuffaloCommand: "events", Description: echoCmd.Short, Aliases: echoCmd.Aliases},
		}
		return json.NewEncoder(os.Stdout).Encode(plugs)
	},
}


events.Emit(events.Event{
  Kind:    "my-event",
})

// buffalo-foo echo "{\"kind\": \"my-event\"}"

github.com/gobuffalo/fizz

GoDoc Build Status Code coverage status Go Report Card

Package fizz is a common DSL for writing SQL migrations

github.com/gobuffalo/flect

GoDoc Build Status Code coverage status Go Report Card

Package flect is a new inflection engine to replace https://github.com/markbates/inflect designed to be more modular, more readable, and easier to fix issues on than the original.

github.com/gobuffalo/genny

GoDoc Build Status Code coverage status Go Report Card

Package genny is a framework for writing modular generators, it however, doesn't actually generate anything. It just makes it easier for you to. :)

github.com/gobuffalo/httptest

GoDoc Build Status Code coverage status Go Report Card

Package httptest was formerly known as https://github.com/markbates/willie. It is used to test HTTP applications easily.

github.com/gobuffalo/packr

GoDoc Build Status Code coverage status Go Report Card

GoDoc


Packr is a simple solution for bundling static assets inside of Go binaries. Most importantly it does it in a way that is friendly to developers while they are developing.

To get an idea of the what and why of packr, please enjoy this short video: https://vimeo.com/219863271.

To install Packr utility

$ go get -u github.com/gobuffalo/packr/packr

To get the dependency

$ go get -u github.com/gobuffalo/packr

The first step in using Packr is to create a new box. A box represents a folder on disk. Once you have a box you can get string or []byte representations of the file.

// set up a new box by giving it a (relative) path to a folder on disk:
box := packr.NewBox("./templates")

// Get the string representation of a file, or an error if it doesn't exist:
html, err := box.FindString("index.html")

// Get the []byte representation of a file, or an error if it doesn't exist:
html, err := box.FindBytes("index.html")

A box represents a folder, and any sub-folders, on disk that you want to have access to in your binary. When compiling a binary using the packr CLI the contents of the folder will be converted into Go files that can be compiled inside of a "standard" go binary. Inside of the compiled binary the files will be read from memory. When working locally the files will be read directly off of disk. This is a seamless switch that doesn't require any special attention on your part.

Assume the follow directory structure:

├── main.go
└── templates
    ├── admin
    │   └── index.html
    └── index.html

The following program will read the ./templates/admin/index.html file and print it out.

package main

import (
  "fmt"

  "github.com/gobuffalo/packr"
)

func main() {
  box := packr.NewBox("./templates")

  s, err := box.FindString("admin/index.html")
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(s)
}

In order to get static files into a Go binary, those files must first be converted to Go code. To do that, Packr, ships with a few tools to help build binaries. See below.

During development, however, it is painful to have to keep running a tool to compile those files.

Packr uses the following resolution rules when looking for a file:

  1. Look for the file in-memory (inside a Go binary)
  2. Look for the file on disk (during development)

Because Packr knows how to fall through to the file system, developers don't need to worry about constantly compiling their static files into a binary. They can work unimpeded.

Packr takes file resolution a step further. When declaring a new box you use a relative path, ./templates. When Packr receives this call it calculates out the absolute path to that directory. By doing this it means you can be guaranteed that Packr can find your files correctly, even if you're not running in the directory that the box was created in. This helps with the problem of testing, where Go changes the pwd for each package, making relative paths difficult to work with. This is not a problem when using Packr.


A box implements the http.FileSystem interface, meaning it can be used to serve static files.

package main

import (
  "net/http"

  "github.com/gobuffalo/packr"
)

func main() {
  box := packr.NewBox("./templates")

  http.Handle("/", http.FileServer(box))
  http.ListenAndServe(":3000", nil)
}

When it comes time to build, or install, your Go binary, simply use packr build or packr install just as you would go build or go install. All flags for the go tool are supported and everything works the way you expect, the only difference is your static assets are now bundled in the generated binary. If you want more control over how this happens, looking at the following section on building binaries (the hard way).

Before you build your Go binary, run the packr command first. It will look for all the boxes in your code and then generate .go files that pack the static files into bytes that can be bundled into the Go binary.

$ packr

Then run your go build command like normal.

NOTE: It is not recommended to check-in these generated -packr.go files. They can be large, and can easily become out of date if not careful. It is recommended that you always run packr clean after running the packr tool.

When you're done it is recommended that you run the packr clean command. This will remove all of the generated files that Packr created for you.

$ packr clean

Why do you want to do this? Packr first looks to the information stored in these generated files, if the information isn't there it looks to disk. This makes it easy to work with in development.


When it comes to building multiple releases you typically want that release to be built in a specific directory.

For example: ./releases

However, because passing a .go file requires absolute paths, we must compile the release in the appropriate absolute path.

GOOS=linux GOARCH=amd64 packr build

Now your project_name binary will be built at the root of your project dir. Great!

All that is left to do is to move that binary to your release dir:

Linux/macOS/Windows (bash)

mv ./project_name ./releases

Windows (cmd):

move ./project_name ./releases

Powershell:

Move-Item -Path .\project_name -Destination .\releases\

If you target for Windows when building don't forget that it's project_name.exe

Now you can make multiple releases and all of your needed static files will be available!

Example Script for building to 3 common targets:

GOOS=darwin GOARCH=amd64 packr build && mv ./project_name ./releases/darwin-project_name \
  && GOOS=linux GOARCH=amd64 packr build && mv ./project_name ./releases/linux-project_name \
  && GOOS=windows GOARCH=386 packr build && mv ./project_name.exe ./releases/project_name.exe \
  && packr clean

The packr command passes all arguments down to the underlying go command, this includes the -v flag to print out go build information. Packr looks for the -v flag, and will turn on its own verbose logging. This is very useful for trying to understand what the packr command is doing when it is run.

github.com/gobuffalo/plush

GoDoc Build Status Code coverage status Go Report Card

Plush is the templating system that Go both needs and deserves. Powerful, flexible, and extendable, Plush is there to make writing your templates that much easier.

Introduction Video

$ go get -u github.com/gobuffalo/plush

Plush allows for the embedding of dynamic code inside of your templates. Take the following example:

<!-- input -->
<p><%= "plush is great" %></p>

<!-- output -->
<p>plush is great</p>

By using the <%= %> tags we tell Plush to dynamically render the inner content, in this case the string plush is great, into the template between the <p></p> tags.

If we were to change the example to use <% %> tags instead the inner content will be evaluated and executed, but not injected into the template:

<!-- input -->
<p><% "plush is great" %></p>

<!-- output -->
<p></p>

By using the <% %> tags we can create variables (and functions!) inside of templates to use later:

<!-- does not print output -->
<%
let h = {name: "mark"}
let greet = fn(n) {
  return "hi " + n
}
%>
<!-- prints output -->
<h1><%= greet(h["name"]) %></h1>
html := `<html>
<%= if (names && len(names) > 0) { %>
	<ul>
		<%= for (n) in names { %>
			<li><%= capitalize(n) %></li>
		<% } %>
	</ul>
<% } else { %>
	<h1>Sorry, no names. :(</h1>
<% } %>
</html>`

ctx := plush.NewContext()
ctx.Set("names", []string{"john", "paul", "george", "ringo"})

s, err := plush.Render(html, ctx)
if err != nil {
  log.Fatal(err)
}

fmt.Print(s)
// output: <html>
// <ul>
// 		<li>John</li>
// 		<li>Paul</li>
// 		<li>George</li>
// 		<li>Ringo</li>
// 		</ul>
// </html>

You can add comments like this:

<%# This is a comment %>

The basic syntax of if/else if/else statements is as follows:

<%
if (true) {
  # do something
} else if (false) {
  # do something
} else {
  # do something else
}
%>

When using if/else statements to control output, remember to use the <%= %> tag to output the result of the statement:

<%= if (true) { %>
  <!-- some html here -->
<% } else { %>
  <!-- some other html here -->
<% } %>

Complex if statements can be built in Plush using "common" operators:

  • == - checks equality of two expressions
  • != - checks that the two expressions are not equal
  • ~= - checks a string against a regular expression (foo ~= "^fo")
  • < - checks the left expression is less than the right expression
  • <= - checks the left expression is less than or equal to the right expression
  • > - checks the left expression is greater than the right expression
  • >= - checks the left expression is greater than or equal to the right expression
  • && - requires both the left and right expression to be true
  • || - requires either the left or right expression to be true
<%= if ((1 < 2) && (someFunc() == "hi")) { %>
  <!-- some html here -->
<% } else { %>
  <!-- some other html here -->
<% } %>

Maps in Plush will get translated to the Go type map[string]interface{} when used. Creating, and using maps in Plush is not too different than in JSON:

<% let h = {key: "value", "a number": 1, bool: true} %>

Would become the following in Go:

map[string]interface{}{
  "key": "value",
  "a number": 1,
  "bool": true,
}

Accessing maps is just like access a JSON object:

<%= h["key"] %>

Using maps as options to functions in Plush is incredibly powerful. See the sections on Functions and Helpers to see more examples.

Arrays in Plush will get translated to the Go type []interface{} when used.

<% let a = [1, 2, "three", "four", h] %>
[]interface{}{ 1, 2, "three", "four", h }

There are three different types that can be looped over: maps, arrays/slices, and iterators. The format for them all looks the same:

<%= for (key, value) in expression { %>
  <%= key %> <%= value %>
<% } %>

The values inside the () part of the statement are the names you wish to give to the key (or index) and the value of the expression. The expression can be an array, map, or iterator type.

<%= for (i, x) in someArray { %>
  <%= i %> <%= x %>
<% } %>
<%= for (val) in someArray { %>
  <%= val %>
<% } %>
<%= for (k, v) in someMap { %>
  <%= k %> <%= v %>
<% } %>
<%= for (v) in someMap { %>
  <%= v %>
<% } %>
type ranger struct {
	pos int
	end int
}

func (r *ranger) Next() interface{} {
	if r.pos < r.end {
		r.pos++
		return r.pos
	}
	return nil
}

func betweenHelper(a, b int) Iterator {
	return &ranger{pos: a, end: b - 1}
}
html := `<%= for (v) in between(3,6) { return v } %>`

ctx := plush.NewContext()
ctx.Set("between", betweenHelper)

s, err := plush.Render(html, ctx)
if err != nil {
  log.Fatal(err)
}
fmt.Print(s)
// output: 45
  • json - converts the interface to a JSON object
  • jsEscape - escapes the interface to be JavaScript safe
  • htmlEscape - escapes the interface to be HTML safe
  • upcase - converts the string to upper case
  • downcase - converts the string to lower case
  • contentFor - stores a block of HTML to be used later
  • contentOf - retrieves a block of HTML previously stored with contentFor
  • markdown - converts the string from Markdown into HTML
  • len - returns the length of the interface
  • debug - returns the %+v of the interface wrapped in <pre> tags.
  • inspect - returns the %+v of the interface
  • range - interate between, and including two numbers
  • between - iterate between, but not including, two numbers
  • until - iterate until a number is reached
  • groupBy - splits a slice or array into n groups
  • env - returns the ENV variable for the specified key
  • truncate - truncates a string to a specified length
  • form - support for the github.com/gobuffalo/tags/form package (Bootstrap version)
  • form_for - support for the github.com/gobuffalo/tags/form package (Bootstrap version) to build a form for a model

Use the contentFor and contentOf helpers to dry up your templates with reusable components.

For example, we can define a snippet that generates a fancy title using contentFor:

<% contentFor("fancy-title") { %>
  <h1 class='fancy'><%= title %></h1>
<% } %>

The fancy-title name is how we will invoke this with contentOf elsewhere in our template:

<%= contentOf("fancy-title", {"title":"Welcome to Plush"}) %>
  • The second map argument is optional, for static content just use <%= contentOf("fancy-title") %>

Rendering this would generate this output:

<h1 class='fancy'>Welcome to Plush</h1>

As you can see, the <%= title %> has been replaced with the Welcome to Plush string.

truncate takes two optional parameters:

  • size - the maximum length of the returned string
  • trail - the string to append at the end of a truncated string, defaults to ...
<p><%= truncate("a long string", {"size": 10, "trail": "[more]"})%></p>
  • asciffy
  • camelize
  • camelize_down_first
  • capitalize
  • dasherize
  • humanize
  • ordinalize
  • parameterize
  • pluralize
  • pluralize_with_size
  • singularize
  • tableize
  • typeify
  • underscore
html := `<p><%= one() %></p>
<p><%= greet("mark")%></p>
<%= can("update") { %>
<p>i can update</p>
<% } %>
<%= can("destroy") { %>
<p>i can destroy</p>
<% } %>
`

ctx := NewContext()

// one() #=> 1
ctx.Set("one", func() int {
  return 1
})

// greet("mark") #=> "Hi mark"
ctx.Set("greet", func(s string) string {
  return fmt.Sprintf("Hi %s", s)
})

// can("update") #=> returns the block associated with it
// can("adsf") #=> ""
ctx.Set("can", func(s string, help HelperContext) (template.HTML, error) {
  if s == "update" {
    h, err := help.Block()
    return template.HTML(h), err
  }
  return "", nil
})

s, err := Render(html, ctx)
if err != nil {
  log.Fatal(err)
}
fmt.Print(s)
// output: <p>1</p>
// <p>Hi mark</p>
// <p>i can update</p>

This package absolutely 100% could not have been written without the help of Thorsten Ball's incredible book, Writing an Interpeter in Go.

Not only did the book make understanding the process of writing lexers, parsers, and asts, but it also provided the basis for the syntax of Plush itself.

If you have yet to read Thorsten's book, I can't recommend it enough. Please go and buy it!

github.com/gobuffalo/pop

GoDoc Build Status Code coverage status Go Report Card

Package pop wraps the absolutely amazing https://github.com/jmoiron/sqlx library. It cleans up some of the common patterns and workflows usually associated with dealing with databases in Go.

Pop makes it easy to do CRUD operations, run migrations, and build/execute queries. Is Pop an ORM? I'll leave that up to you, the reader, to decide.

Pop, by default, follows conventions that were defined by the ActiveRecord Ruby gem, http://www.rubyonrails.org. What does this mean?

  • Tables must have an "id" column and a corresponding "ID" field on the struct being used.
  • If there is a timestamp column named "created_at", "CreatedAt" on the struct, it will be set with the current time when the record is created.
  • If there is a timestamp column named "updated_at", "UpdatedAt" on the struct, it will be set with the current time when the record is updated.
  • Default databases are lowercase, underscored versions of the struct name. Examples: User{} is "users", FooBar{} is "foo_bars", etc...

github.com/gobuffalo/suite

GoDoc Build Status Code coverage status Go Report Card

Suite is a package meant to make testing gobuffalo.io applications easier.

This is the entry point into your unit testing suite. The Test_ActionSuite(t *testing.T) function is compatible with the go test command, and it should:

  • Create and configure your new test suite instance (ActionSuite in this case)
  • Call suite.Run with the *testing.T passed by the Go testing system, and your new ActionSuite instance
package actions_test

import (
	"testing"

	"github.com/gobuffalo/suite"
	"github.com/gobuffalo/toodo/actions"
)

type ActionSuite struct {
	*suite.Action
}

func Test_ActionSuite(t *testing.T) {
	as := &ActionSuite{suite.NewAction(actions.App())}
	suite.Run(t, as)
}

This is where you write your actual test logic. The rules for test names are similar, but not the same, as with go test:

  • Each test is a method on your *ActionSuite
  • Test method names should start with Test (note the upper case T)
  • Test methods should have no arguments

A few additional notes:

  • To avoid race conditions on the testing database, always use the ActionSuite variable called DB to access the database (not your production app's database)
  • You can access the raw *testing.T value if needed with as.T()
  • ActionSuite has support for testify's require package and assert package
  • ... So try to use one of those instead packages of using the raw methods on the *testing.T
  • The default database that suite will connect to is called testing in your database.yml
package actions_test

import (
	"fmt"

	"github.com/gobuffalo/toodo/models"
)

func (as *ActionSuite) Test_TodosResource_List() {
	todos := models.Todos{
		{Title: "buy milk"},
		{Title: "read a good book"},
	}
	for _, t := range todos {
		err := as.DB.Create(&t)
		as.NoError(err)
	}

	res := as.HTML("/todos").Get()
	body := res.Body.String()
	for _, t := range todos {
		as.Contains(body, fmt.Sprintf("<h2>%s</h2>", t.Title))
	}
}

func (as *ActionSuite) Test_TodosResource_New() {
	res := as.HTML("/todos/new").Get()
	as.Contains(res.Body.String(), "<h1>New Todo</h1>")
}

func (as *ActionSuite) Test_TodosResource_Create() {
	todo := &models.Todo{Title: "Learn Go"}
	res := as.HTML("/todos").Post(todo)
	as.Equal(301, res.Code)
	as.Equal("/todos", res.Location())

	err := as.DB.First(todo)
	as.NoError(err)
	as.NotZero(todo.ID)
	as.NotZero(todo.CreatedAt)
	as.Equal("Learn Go", todo.Title)
}

func (as *ActionSuite) Test_TodosResource_Create_Errors() {
	todo := &models.Todo{}
	res := as.HTML("/todos").Post(todo)
	as.Equal(422, res.Code)
	as.Contains(res.Body.String(), "Title can not be blank.")

	c, err := as.DB.Count(todo)
	as.NoError(err)
	as.Equal(0, c)
}

func (as *ActionSuite) Test_TodosResource_Update() {
	todo := &models.Todo{Title: "Lern Go"}
	verrs, err := as.DB.ValidateAndCreate(todo)
	as.NoError(err)
	as.False(verrs.HasAny())

	res := as.HTML("/todos/%s", todo.ID).Put(&models.Todo{ID: todo.ID, Title: "Learn Go"})
	as.Equal(200, res.Code)

	err = as.DB.Reload(todo)
	as.NoError(err)
	as.Equal("Learn Go", todo.Title)
}

Often it is useful to load a series of data into the database at the start of the test to make testing easier. For example, you need to have a user in the database to log a person into the application, or you need some data in the database to test destroying that data. Fixtures let us solve these problems easily.

First you need to setup your test suite to use fixtures. You can do this by using suite.NewActionWithFixtures or suite.NewModelWithFixtures methods to create new test suites that take a packd.Box pointing to where the files for this suite live.

package actions

import (
	"testing"

	"github.com/gobuffalo/packr"
	"github.com/gobuffalo/suite"
)

type ActionSuite struct {
	*suite.Action
}

func Test_ActionSuite(t *testing.T) {
	action, err := suite.NewActionWithFixtures(App(), packr.NewBox("../fixtures"))
	if err != nil {
		t.Fatal(err)
	}

	as := &ActionSuite{
		Action: action,
	}
	suite.Run(t, as)
}

Once your suite is set up, you can create N numbers of *.toml files in the directory you've chosen for your fixtures, in this example, ../fixtures.

[[scenario]]
name = "lots of widgets"

  [[scenario.table]]
    name = "widgets"

    [[scenario.table.row]]
      id = "<%= uuidNamed("widget") %>"
      name = "This is widget #1"
      body = "some widget body"
      created_at = "<%= now() %>"
      updated_at = "<%= now() %>"

    [[scenario.table.row]]
      id = "<%= uuid() %>"
      name = "This is widget #2"
      body = "some widget body"
      created_at = "<%= now() %>"
      updated_at = "<%= now() %>"

  [[scenario.table]]
    name = "users"

    [[scenario.table.row]]
      id = "<%= uuid() %>"
      name = "Mark Bates"
      admin = true
      price = 19.99
      widget_id = "<%= uuidNamed("widget") %>"
      created_at = "<%= now() %>"
      updated_at = "<%= now() %>"

The *.toml files all get run through https://github.com/gobuffalo/plush before they're decoded, so you can make use of the helpful helper methods that ship with Plush.

We've also add a couple of useful helpers for you as well:

  • uuid() - returns a new github.com/gobuffalo/uuid.UUID
  • now() - returns time.Now()
  • uuidNamed(name) - will attempt to return a previously declared UUID with that name, useful, for relations/associations. If there was one that wasn't defined with that name, a new one will be created.
  • hash(string, opts) - will create the hashed value of the string (useful for creating a password), you can define the cost as an opts (the default is bcrypt.DefaultCost)

In your suite tests you need to call the LoadFixture method giving it the name of the fixtures you would like to use for this test.

func (as *ActionSuite) Test_WidgetsResource_List() {
	as.LoadFixture("lots of widgets")
	res := as.HTML("/widgets").Get()

	body := res.Body.String()
	as.Contains(body, "widget #1")
	as.Contains(body, "widget #2")
}
  • Can I call LoadFixture more than once in a test? - Absolutely! Call it as many times as you want!
  • Can I load multiple rows into a table in one scenario? - Absolutely!
  • Can I load data into multiple tables in one scenario? - Absolutely!
  • Will it load all my fixtures? - No, you have to load specific scenarios, so don't be afraid to create lots of scenarios and only call the ones you need per test.
  • Will this polute my database, and how do I clear data between tests? - No need to worry, the suite will truncate any data in your database between test runs, so you never have to worry about it.

github.com/gobuffalo/tags

GoDoc Build Status Code coverage status Go Report Card

Easily build HTML tags in Go! This package is especially useful when using http://gobuffalo.io.

Tags has a minimum Go dependency of 1.8.1.

To get this lib just get it via go get

go get -u -v github.com/gobuffalo/tags/...

In order to run the tests just do it with a regular

go test ./...

Documentation is currently in this repository Wiki, you can find there instructions on how to use tags within your app.

If you want to contribute, please read this article first: Contributing to Open Source Git Repositories in Go. It shows how to configure your git environment to avoid common pitfalls. This article is recommended to all those who are looking to contribute to any Go projects.

^ Taken from gobuffalo.io

The way we release in Tags is:

  1. We use development branch to accumulate changes to be released
  2. Once we decide to make a release we send a PR from development to master with those changes to be added.
  3. Once that PR gets merged we tag a new release with the vX.X.X scheme.

github.com/gobuffalo/validate

GoDoc Build Status Code coverage status Go Report Card

Build Status GoDoc

This package provides a framework for writing validations for Go applications. It does provide you with few validators, but if you need others you can easly build them.

$ go get github.com/gobuffalo/validate

Using validate is pretty easy, just define some Validator objects and away you go.

Here is a pretty simple example:

package main

import (
	"log"

	v "github.com/gobuffalo/validate"
)

type User struct {
	Name  string
	Email string
}

func (u *User) IsValid(errors *v.Errors) {
	if u.Name == "" {
		errors.Add("name", "Name must not be blank!")
	}
	if u.Email == "" {
		errors.Add("email", "Email must not be blank!")
	}
}

func main() {
	u := User{Name: "", Email: ""}
	errors := v.Validate(&u)
	log.Println(errors.Errors)
  // map[name:[Name must not be blank!] email:[Email must not be blank!]]
}

In the previous example I wrote a single Validator for the User struct. To really get the benefit of using go-validator, as well as the Go language, I would recommend creating distinct validators for each thing you want to validate, that way they can be run concurrently.

package main

import (
	"fmt"
	"log"
	"strings"

	v "github.com/gobuffalo/validate"
)

type User struct {
	Name  string
	Email string
}

type PresenceValidator struct {
	Field string
	Value string
}

func (v *PresenceValidator) IsValid(errors *v.Errors) {
	if v.Value == "" {
		errors.Add(strings.ToLower(v.Field), fmt.Sprintf("%s must not be blank!", v.Field))
	}
}

func main() {
	u := User{Name: "", Email: ""}
	errors := v.Validate(&PresenceValidator{"Email", u.Email}, &PresenceValidator{"Name", u.Name})
	log.Println(errors.Errors)
        // map[name:[Name must not be blank!] email:[Email must not be blank!]]
}

That's really it. Pretty simple and straight-forward Just a nice clean framework for writing your own validators. Use in good health.

To make it even simpler, this package has a children package with some nice built-in validators.

package main

import (
	"log"

	"github.com/gobuffalo/validate"
	"github.com/gobuffalo/validate/validators"
)

type User struct {
	Name  string
	Email string
}


func main() {
	u := User{Name: "", Email: ""}
	errors := validate.Validate(
		&validators.EmailIsPresent{Name: "Email", Field: u.Email, Message: "Mail is not in the right format."},
		&validators.StringIsPresent{Field: u.Name, Name: "Name"},
	)
	log.Println(errors.Errors)
	// map[name:[Name can not be blank.] email:[Mail is not in the right format.]]
}

All fields are required for each validators, except Message (every validator has a default error message).

A full list of available validators can be found at https://godoc.org/github.com/gobuffalo/validate/validators.

github.com/gobuffalo/x

GoDoc Build Status Code coverage status Go Report Card

This collection of packages is meant to be a "testing" ground for Buffalo packages that may or may not get included in future versions of Buffalo.

Feedback on these packages, their use, etc... is greatly appreciated.

These packages should always work with the "latest" version of Buffalo, i.e. the master branch. Exceptions will be noted.

github.com/markbates/grift

GoDoc Build Status Code coverage status Go Report Card

Grift is a very simple library that allows you to write simple "task" scripts in Go and run them by name without having to write big main type of wrappers. Grift is similar to, and inspired by, Rake.

Excellent question! When building applications there comes a point where you need different scripts to do different things. For example, you might want a script to seed your database, or perhaps a script to parse some logs, etc...

Grift lets you write these scripts using Go in a really simple and extensible way.

Installation is really easy using go get.

$ go get github.com/markbates/grift

You can confirm the installation by running:

$ grift jim

Apart from having the binary installed, the only other requirement is that the package you place your grifts in is called grifts. That's it.

By running the following command:

$ grift init

When you run the init sub-command Grift will generate a new grifts package and create a couple of simple grifts for you.

$ grift list
$ grift hello

That's really it! Grift is meant to be simple. Write your grifts, use the full power of Go to do it.

For more information I would highly recommend checking out the docs.

package grifts

import (
	"errors"
	"fmt"
	"os"
	"strings"

	. "github.com/markbates/grift/grift"
)

var _ = Add("boom", func(c *Context) error {
	return errors.New("boom!!!")
})

var _ = Add("hello", func(c *Context) error {
	fmt.Println("Hello World!")
	return nil
})

var _ = Add("hello", func(c *Context) error {
	fmt.Println("Hello World! Again")
	err := Run("db:migrate", c)
	if err != nil {
		return err
	}
	dir, err := os.Getwd()
	if err != nil {
		return err
	}
	fmt.Printf("### dir -> %+v\n", dir)
	return nil
})

var _ = Add("env:print", func(c *Context) error {
	if len(c.Args) >= 1 {
		for _, e := range c.Args {
			fmt.Printf("%s=%s\n", e, os.Getenv(e))
		}
	} else {
		for _, e := range os.Environ() {
			pair := strings.Split(e, "=")
			fmt.Printf("%s=%s\n", pair[0], os.Getenv(pair[0]))
		}
	}

	return nil
})

var _ = Namespace("db", func() {
    Desc("migrate", "Migrates the databases")
    Set("migrate", func(c *Context) error {
            fmt.Println("db:migrate")
            fmt.Printf("### args -> %+v\n", c.Args)
            return nil
    })
}