# Development

- Architecture
- Write Plugins
  - Register a new callback
  - Delete an existing callback
  - Replace an existing callback
  - Register callback orders
  - Pre-Defined Callbacks

## Architecture

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

    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`

    // 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

## 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

- Update callbacks

- Query callbacks

- Delete callbacks

- 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:

    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 to view all available API