# Development

<!-- toc -->

## Architecture

Gorm use chainable API, `*gorm.DB` is the bridge of chains, for each chain API, it will create a new relation.

```go
db, err := gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable")

// create a new relation
db = db.Where("name = ?", "jinzhu")

// filter even more
if SomeCondition {
    db = db.Where("age = ?", 20)
} else {
    db = db.Where("age = ?", 30)
}
if YetAnotherCondition {
    db = db.Where("active = ?", 1)
}
```

When we start to perform any operations, GROM will create a new `*gorm.Scope` instance based on current `*gorm.DB`

```go
// perform a querying operation
db.First(&user)
```

And based on current operation's type, it will call registered `creating`, `updating`, `querying`, `deleting` or `row_querying` callbacks to run the operation.

For above example, will call `querying` callbacks, refer [Querying Callbacks](callbacks.html#querying-an-object)

## Write Plugins

GORM itself is powered by `Callbacks`, so you could fully customize GORM as you want

### Register a new callback

    func updateCreated(scope *Scope) {
        if scope.HasColumn("Created") {
            scope.SetColumn("Created", NowFunc())
        }
    }

    db.Callback().Create().Register("update_created_at", updateCreated)
    // register a callback for Create process

### Delete an existing callback

    db.Callback().Create().Remove("gorm:create")
    // delete callback `gorm:create` from Create callbacks

### Replace an existing callback

    db.Callback().Create().Replace("gorm:create", newCreateFunction)
    // replace callback `gorm:create` with new function `newCreateFunction` for Create process

### Register callback orders

    db.Callback().Create().Before("gorm:create").Register("update_created_at", updateCreated)
    db.Callback().Create().After("gorm:create").Register("update_created_at", updateCreated)
    db.Callback().Query().After("gorm:query").Register("my_plugin:after_query", afterQuery)
    db.Callback().Delete().After("gorm:delete").Register("my_plugin:after_delete", afterDelete)
    db.Callback().Update().Before("gorm:update").Register("my_plugin:before_update", beforeUpdate)
    db.Callback().Create().Before("gorm:create").After("gorm:before_create").Register("my_plugin:before_create", beforeCreate)

### Pre-Defined Callbacks

GORM has defiend callbacks to perform its CRUD operations, check them out before start write your plugins

- [Create callbacks](https://github.com/jinzhu/gorm/blob/master/callback_create.go)

- [Update callbacks](https://github.com/jinzhu/gorm/blob/master/callback_update.go)

- [Query callbacks](https://github.com/jinzhu/gorm/blob/master/callback_query.go)

- [Delete callbacks](https://github.com/jinzhu/gorm/blob/master/callback_delete.go)

- Row Query callbacks

Row Query callbacks will be called when run `Row` or `Rows`, by default there is no registered callbacks for it, you could register a new one like:

```go
func updateTableName(scope *gorm.Scope) {
  scope.Search.Table(scope.TableName() + "_draft") // append `_draft` to table name
}

db.Callback().RowQuery().Register("publish:update_table_name", updateTableName)
```

View [https://godoc.org/github.com/jinzhu/gorm](https://godoc.org/github.com/jinzhu/gorm) to view all available API
