Table of Contents
- Introduction
- Prerequisites
- Installation
- Creating a New Buffalo Project
- Building the Web Application
- Adding Routes and Handlers
- Creating Views and Templates
- Working with Models and Database
- Testing the Web Application
-
Introduction
In this tutorial, we will learn how to build a Go web application using the Buffalo framework. Buffalo is a highly productive web framework that follows the convention over configuration principle, allowing developers to focus on writing business logic instead of spending time on setting up the project structure. By the end of this tutorial, you will have a basic understanding of Buffalo and its core components, such as routes, handlers, views, and models.
Prerequisites
To follow along with this tutorial, you should have a basic understanding of the Go programming language. You will also need to have Go installed on your machine. If you haven’t installed Go yet, please refer to the official Go website (https://golang.org/doc/install) for instructions on how to install it.
Installation
Before we can start building our web application, we need to install Buffalo. Open your terminal or command prompt and run the following command to install Buffalo:
go get -u github.com/gobuffalo/buffalo/buffalo
Once the installation is complete, you can verify that Buffalo is installed correctly by running the following command:
buffalo version
If everything is set up correctly, you should see the version number of Buffalo printed in the console.
Creating a New Buffalo Project
Now that Buffalo is installed, let’s create a new project. In your terminal, navigate to the directory where you want to create the project and run the following command:
buffalo new myapp
This command will create a new Buffalo project named “myapp” in a directory called “myapp” as well. Change your current directory to the newly created project:
cd myapp
Building the Web Application
Now, let’s build our web application. Buffalo provides a built-in development server that makes it easy to preview our application as we develop it. To start the development server, run the following command:
buffalo dev
Buffalo will start the server and print the URL where you can access your application in the console. Open your web browser and visit the provided URL. You should see a default welcome page.
Adding Routes and Handlers
In Buffalo, routes are defined in the routes
folder in a file named app.go
. Let’s add a new route that maps to a handler function. Open the app.go
file and add the following code:
package actions
import (
"github.com/gobuffalo/buffalo"
)
func init() {
app.GET("/", HomeHandler)
}
func HomeHandler(c buffalo.Context) error {
return c.Render(200, r.HTML("index.html"))
}
In this code, we define a new route that maps the root URL (“/”) to the HomeHandler
function. The HomeHandler
function renders the index.html
template.
Creating Views and Templates
Buffalo uses the Plush templating engine to render views. Views and templates are stored in the templates
folder. Let’s create a simple index.html
template. Create a new file named index.html
in the templates
folder with the following content:
<h1>Welcome to myapp!</h1>
<p>This is the default home page.</p>
Now, if you refresh your browser, you should see the content of your index.html
template rendered.
Working with Models and Database
Buffalo comes with a built-in ORM (Object-Relational Mapping) library called Pop. This allows us to work with databases easily. Let’s create a simple model and perform CRUD (Create, Read, Update, Delete) operations.
First, let’s create a new model. Run the following command to generate a new model file:
buffalo g model todo title content
This command will generate a new model file named todo.go
in the models
folder. Open the todo.go
file and modify it as follows:
package models
import (
"github.com/gobuffalo/buffalo"
"github.com/gobuffalo/pop/v5"
"github.com/pkg/errors"
)
type Todo struct {
ID int `json:"id" db:"id"`
Title string `json:"title" db:"title"`
Content string `json:"content" db:"content"`
}
func (t Todo) Create(c buffalo.Context) error {
if err := c.Bind(&t); err != nil {
return errors.WithStack(err)
}
tx, ok := c.Value("tx").(*pop.Connection)
if !ok {
return errors.WithStack(errors.New("no transaction found"))
}
verrs, err := tx.ValidateAndCreate(&t)
if err != nil {
return errors.WithStack(err)
}
if verrs.HasAny() {
// handle validation errors
}
return c.Render(200, r.JSON(t))
}
func (t Todo) List(c buffalo.Context) error {
tx, ok := c.Value("tx").(*pop.Connection)
if !ok {
return errors.WithStack(errors.New("no transaction found"))
}
todos := []Todo{}
if err := tx.All(&todos); err != nil {
return errors.WithStack(err)
}
return c.Render(200, r.JSON(todos))
}
In this code, we define a Todo
struct as our model and add Create
and List
methods. The Create
method handles creating a new todo item, and the List
method retrieves all todo items from the database.
To generate the migrations and update the database schema, run the following command:
buffalo db migrate
This command will create a new migration file and apply it to the database.
To create a route for our new model’s actions, open the app.go
file and modify it as follows:
package actions
import (
"github.com/gobuffalo/buffalo"
"github.com/your-username/myapp/models"
)
// ...
func init() {
app.GET("/", HomeHandler)
app.POST("/todos", models.Todo{}.Create) // Add this line
app.GET("/todos", models.Todo{}.List) // Add this line
}
We have added two new routes—one for creating a todo item (POST /todos
) and another for listing all todo items (GET /todos
).
Testing the Web Application
Buffalo provides a testing framework to help us write tests for our web application easily. Let’s create a basic test for our todo endpoints.
Create a new file named todo_test.go
in the actions
folder and add the following code:
package actions
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gobuffalo/buffalo"
"github.com/your-username/myapp/models"
"github.com/stretchr/testify/require"
)
func TestTodoCreate(t *testing.T) {
app := buffalo.New(buffalo.Options{})
app.POST("/todos", models.Todo{}.Create)
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/todos", nil)
c := app.NewContext(req, w)
err := models.DB.TruncateAll()
require.NoError(t, err)
res := app.ServeHTTP(c)
require.Equal(t, 200, res.Code)
// Assert the response here
}
func TestTodoList(t *testing.T) {
app := buffalo.New(buffalo.Options{})
app.GET("/todos", models.Todo{}.List)
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/todos", nil)
c := app.NewContext(req, w)
err := models.DB.TruncateAll()
require.NoError(t, err)
res := app.ServeHTTP(c)
require.Equal(t, 200, res.Code)
// Assert the response here
}
In these tests, we create a new Buffalo application, define routes for the todo endpoints, and send test requests to these endpoints. We then assert the expected responses.
To run the tests, execute the following command:
buffalo test ./...
This command will run all tests in the current project directory and its subdirectories.
Conclusion
Congratulations! You have built a simple Go web application using the Buffalo framework. In this tutorial, we covered the basics of Buffalo, including setting up a new project, building routes, handling requests and responses, working with views and templates, using models and the database, and writing tests.
Buffalo provides many more features and options for building robust web applications. I encourage you to explore the Buffalo documentation (https://gobuffalo.io) to learn more about its capabilities and best practices.
Remember to experiment with different features and expand your application according to your needs. Happy coding!