Wheel Doc


1  MVC

MVC is a software architecture pattern which separates the application in three layers: Model, View and Controller. Model holds the business logic and interacts with the database, View is the layer which interacts with the users and the Controller handles the comunication between Model and View.

Wheel is MVC architecture based. But the Controller layer is called of Handler.

1.1  Model

The models on Wheel are inside each resource directory, which is under directory app. It means if your application has a resource called person the model is in the directory:


1.2  View

Just like models, views on Wheel are inside each resource directory, which is under directory app. It means if your application has a resource called person the view is in the directory:


1.3  Controller/Handler

Wheel calls controllers as handlers. All handlers are together within the same directory app/handlers.


2  RESTful

Wheel is based in resources. By default, each resource has its own create, read, update and destroy routes identified by an unique pair of URL and HTTP method. For example, the default routes of the resource person are:

  router.HandleFunc("/people", handlers.PersonList).Methods("GET")
  router.HandleFunc("/people/{id}", handlers.PersonShow).Methods("GET")
  router.HandleFunc("/people", handlers.PersonCreate).Methods("POST")
  router.HandleFunc("/people/{id}", handlers.PersonUpdate).Methods("PUT")
  router.HandleFunc("/people/{id}", handlers.PersonDestroy).Methods("DELETE")

3  JWT

JSON Web Tokens work as credentials which grant access to resources.

Wheel by default generates an unique JWT for each successful sing in request. See more details on Sessions Default Resources section.

When you create a new project with Wheel, it generates a pair of key files. One of them is the private key and it is used to generate the JWT while siging in and the other is used to validate the JWT and grant application access for each subsequent requests. See both keys in directory config/keys/.

You can generate by yourself the pair of key files. Just follow the example below:

$> cd /path/to/app/config/keys
$> openssl genrsa -out app.key.rsa 2048
$> openssl rsa -in app.key.rsa -pubout > app.key.rsa.pub

4  Session Control

Wheel has a built-in Session Control. Check all functionalities below:

Sing upSign up function for internet public audience.
Sign inAuthenticates users with valid credentials. Returns a token (JWT) for use in subsequent requests.
AuthorizationAfter successful authentication, authorizes (or not) requests with a valid token.
Sign OutSigned in users can sign out.
Password RecoveryNevermind if any user forgets password. Wheel sends internationalized email for password recovery and manages the entire process.

5  Middleware

Middleware holds the functions that are executed before requests reach the handler.

Wheel generates by default two middlewares:

  1. loggingMiddleware: this function logs all request to the application.
  2. authorizeMiddleware: this function handles the authorization of the application.

6  Authorization

Authorization defines if requests from users has or hasn't permission to be executed. By default, Wheel defines three user roles: public, signed_in and admin.

publicInternet public audience.
signed_inregular signed in users.
adminadministrators/managers of the application.

The whole authorization proccess is executed in a middleware and it has two steps. First step is to identify the role of the current user. Second is to check permissions. The method authorizeMiddleware in routes/middleware.go identifies the user role and the file routes/authorize.go has permissions rules.

7  Users Management

Users management are resources only allowed for admin users. They can:

  • List all users
  • Show a single users
  • Create users
  • Update users
  • Destroy users

8  ORM

Wheel uses the GORM which helps to interact with the database.

9  Migration

Migration is a feature of GORM. Because of it, you don't need to write SQL to change the database schema.

Wheel creates the file db/schema/migrate.go when generates a new project. The default generated migration creates the user's table, the admin user, the session's table and theirs relationship.

  package schema

  import (

  func Migrate() {

    _, err := user.FindByEmail("user@example.com")
    if err != nil {
      model.Db.Create(&entities.User{Name: "User Name", Email: "user@example.com", Password: crypto.SetPassword("!Secret.123!"), Locale: "en", Admin: true})

    model.Db.Model(&entities.Session{}).AddForeignKey("user_id", "users(id)", "NO ACTION", "NO ACTION")

Wheel updates the file db/schema/migrate.go when you create a new CRUD.

$> wheel generate scaffold person name:string email:string birth_day:datetime

It will add to db/schema/migrate.go file the following line:


10  Search Engine

The Search Engine is a powerful filter for listing data. You can filter by one or more columns of a table in the database and specify the criteria. In the request URL, you need to set the search paramenter as a hash. The key of each element in hash is composed by the name of the column and the criterion separated by an underline "_".

The following two examples we are assuming a database table named people and it has the columns name, email and birth_day.

First example: listing people whose email is equals to "user@example.com"

$> curl -X GET http://localhost:8081/people?search[email_eq]=user@example.com

It will run the following SQL:

  SELECT * FROM people WHERE email = "user@example.com"

Second example: listing people whose emails are in a list.

$> curl -X GET http://localhost:8081/people?search[email_in]=user@example.com,test@domain.com

It will run the following SQL:

  SELECT * FROM people WHERE email IN ("user@example.com", "test@domain.com")

Third example: listing people whose name contains the letter "a" and were born after the year 1999.

$> curl -X GET http://localhost:8081/people?search[name_cont]=a&search[birth_day_gt]=1999-12-31

It will run the following SQL:

  SELECT * FROM people WHERE name ILIKE "%a%" AND birth_day > '1999-12-31'

All the availables criteria you can find below:

noteqis not equal toSELECT * FROM [TABLE] WHERE [COLUMN] <> '[VALUE]'
notcontdoes not containSELECT * FROM [TABLE] WHERE [COLUMN] NOT ILIKE '%[VALUE]%'
notstartdoes not start withSELECT * FROM [TABLE] WHERE [COLUMN] NOT ILIKE '[VALUE]%'
notenddoes not end withSELECT * FROM [TABLE] WHERE [COLUMN] NOT ILIKE '%[VALUE]'
inincludesSELECT * FROM [TABLE] WHERE [COLUMN] IN ([VALUE_1], [VALUE_2], ... , [VALUE_N])
notindoes not includeSELECT * FROM [TABLE] WHERE [COLUMN] NOT IN ([VALUE_1], [VALUE_2], ... , [VALUE_N])
gteqgreat than or equalSELECT * FROM [TABLE] WHERE [COLUMN] >= [VALUE]
lteqless than or equalSELECT * FROM [TABLE] WHERE [COLUMN] <= [VALUE]
trueis trueSELECT * FROM [TABLE] WHERE [COLUMN] = 't'
falseis falseSELECT * FROM [TABLE] WHERE [COLUMN] = 'f'

11  Pagination

Just like Search Engine, Pagination is a feature for listing data.

Pagination has two parameters:

pagePage you want to seeDefault value is 1
per_pageAmount of entries per pageDefault value is 20


$> curl -X GET http://localhost:8081/people?page=2&per_page=10

Returns something like:

    "pagination": {
        "current_page": 2,
        "total_pages": 10,
        "total_entries": 96
    "movies": [

12  Ordering

Ordering is also a feature for listing data and can work together with Search Engine and Pagination. You can order by any SQL command.


$> curl -X GET http://localhost:8081/people?order=birth_day%20DESC

13  Send Mail

Wheel has support for sending emails. There are two scenarios where it happens:

  1. After sing up
  2. Password recovery

The short example to send emails is:

  import /app/path/commons/mailer
  mailer.AddTo("Recipient Name", "recipient@email.com")
  subject := "Hello world"
  body := "This is a test email message"
  go mailer.Send(subject, body, true)

14  Internationalization (I18n)

In previous item you learned how to use Wheel's internals to send emails. You can use internationalization to send emails using the recipient user's language.

The current version of Wheel has the following locales available.

  • en
  • pt-BR

To add a new locale to your project, get the file config/locales/en.yml as example, translate the words/phrases and save as "the locale code" plus .yml. For example, if you want to translate to french save the new locale file as config/locales/fr.yml. After, edit the config/app.yml and add to option locale the new locale code.

15  Log

You can log the application events for auditing or debuging. Logs are showed in stdout and persisted in file log/app.log.

  import /app/path/commons/log
  log.Info.Println("Hello World!")

The function Info from package log is nothing but a classification for the event. Events classes are:

  • Debug
  • Info
  • Warn
  • Error
  • Fatal
Each one has with its own color to you quickly identify the event class.