ar

package module
v0.0.0-...-c37112f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 11, 2015 License: MIT Imports: 11 Imported by: 3

README

argen

argen is an ORM code-generation tool for Go, provides ActiveRecord-like functionality for your types.

Installation

$ go get -u github.com/monochromegane/argen/...

Quick start

  1. Define a table mapping struct in main.go.
  2. Mark it up with a +AR annotation in an adjacent comment like so:
//+AR
type User struct{
	Id int `db:"pk"`
	Name string
	Age int
}

And at the command line, simply type:

$ argen main.go

You should see new files, named *_gen.go.

And you can use ActiveRecord-like functions.

db, _ := sql.Open("sqlite3", "foo.db")
Use(db)

u := User{Name: "test", Age: 20}
u.Save()
//// INSERT INTO users (name, age) VALUES (?, ?); [test 20]

User{}.Where("name", "test").And("age", ">", 20).Query()
//// SELECT users.id, users.name, users.age FROM users WHERE name = ? AND age > ?; [test 20]

ActiveRecord-like functions

Setup
db, _ := sql.Open("sqlite3", "foo.db")

// Set db
Use(db)
Create record
u := User{Name: "test", Age: 20}
u.Save()

or

// XxxParams has same fields to original type.
User{}.Create(UserParams{Name: "test", Age: 20})
Query
// Get the first record
User{}.First()
//// SELECT users.id, users.name, users.age FROM users ORDER BY id ASC LIMIT ?; [1]

// Get the last record
User{}.Last()
//// SELECT users.id, users.name, users.age FROM users ORDER BY id DESC LIMIT ?; [1]

// Get the record by Id
User{}.Find(1)
//// SELECT users.id, users.name, users.age FROM users WHERE id = ? LIMIT ?; [1 1]

// Get all record
User{}.All().Query()
//// SELECT users.id, users.name, users.age FROM users;
Query with conditions
// Get the first matched record
User{}.FindBy("name", "test")
//// SELECT users.id, users.name, users.age FROM users WHERE name = ? LIMIT ?; [test 1]

// Get the first matched record
User{}.Where("name", "test").QueryRow()
//// SELECT users.id, users.name, users.age FROM users WHERE name = ?; [test]

// Get the all matched records
User{}.Where("name", "test").Query()
//// SELECT users.id, users.name, users.age FROM users WHERE name = ?; [test]

// And
User{}.Where("name", "test").And("age", ">", 20).Query()
//// SELECT users.id, users.name, users.age FROM users WHERE name = ? AND age > ?; [test 20]
// Count
User{}.Count()
//// SELECT COUNT(*) FROM users;

// Exists
User{}.Exists()
//// SELECT 1 FROM users LIMIT ?; [1]

// Select
User{}.Select("id", "name").Query()
//// SELECT users.id, users.name FROM users;

// Order
User{}.Order("name", "ASC").Query()
//// SELECT users.id, users.name, users.age FROM users ORDER BY name ASC;

// Limit and offset
User{}.Limit(1).Offset(2).Query()
//// SELECT users.id, users.name, users.age FROM users LIMIT ? OFFSET ?; [1 2]

// GroupBy and having
User{}.Group("name").Having("count(name)", 2).Query()
//// SELECT users.id, users.name, users.age FROM users GROUP BY name HAVING count(name) = ?; [2]
Update
user, _ := User{}.Find(1)

// Update an existing struct
user.Name = "a"
user.Save()
//// UPDATE users SET id = ?, name = ?, age = ? WHERE id = ?; [1 a 20 1]

// Update attributes with validation
user.Update(UserParams{Name: "b"})
//// UPDATE users SET id = ?, name = ?, age = ? WHERE id = ?; [1 b 20 1]

// Update attributes without validation
user.UpdateColumns(UserParams{Name: "c"})
//// UPDATE users SET id = ?, name = ?, age = ? WHERE id = ?; [1 b 20 1]
Delete
user, _ := User{}.Find(1)

// Delete an existing struct
user.Destroy()
//// DELETE FROM users WHERE id = ?; [1]

Associations

Has One

Add association function to your type:

func (m User) hasOnePost() *ar.Association {
        return nil
}

And type argen or go generate on your command line.

user, _ := User{}.Create(UserParams{Name: "user1"})
user.BuildPost(PostParams{Name: "post1"}).Save()

// Get the related record
user.Post()
//// SELECT posts.id, posts.user_id, posts.name FROM posts WHERE user_id = ?; [1]

// Join
user.JoinsPost().Query()
//// SELECT users.id, users.name, users.age FROM users INNER JOIN posts ON posts.user_id = users.id;
Has Many

Add association function to your type:

func (m User) hasManyPosts() *ar.Association {
        return nil
}

And type argen or go generate on your command line.

user, _ := User{}.Create(UserParams{Name: "user1"})
user.BuildPost(PostParams{Name: "post1"}).Save()

// Get the related records
user.Posts()
//// SELECT posts.id, posts.user_id, posts.name FROM posts WHERE user_id = ?; [1]

// Join
user.JoinsPosts()
//// SELECT users.id, users.name, users.age FROM users INNER JOIN posts ON posts.user_id = users.id;
Belongs To

Add association function to your type:

func (p Post) belongsToUser() *ar.Association {
        return nil
}

And type argen or go generate on your command line.

u, _ := User{}.Create(UserParams{Name: "user1"})
post, _ := u.BuildPost(PostParams{Name: "post1"})
post.Save()

// Get the related record
post.User()
//// SELECT users.id, users.name, users.age FROM users WHERE id = ?; [1]

// Join
post.JoinsUser().Query()
//// SELECT posts.id, posts.user_id, posts.name FROM posts INNER JOIN users ON users.id = posts.user_id;

Validation

Add validation function to your type:

func (u User) validatesName() ar.Rule {
	// Define rule for "name" column
	return ar.MakeRule().Format().With("[a-z]")
}

You specify target column by naming validatesXxx.

Rules
// presence
Presence()

// format
Formart().With("regex")

// numericality
Numericality().OnlyInteger().GreaterThan(10)
Trigger
// OnCreate
OnCreate()

// OnUpdate
OnUpdate()
Method chain

Validation rules has a chainable API. you could use it like this.

ar.MakeRule().
	Presence().
	Format().With("[a-z]").
	OnCreate()
Custom validation

Add custom validation function to your type:

func (p Post) validateCustom() ar.Rule {
        return ar.CustomRule(func(errors *ar.Errors) {
                if p.Name != "name" {
                        errors.Add("name", "must be name")
                }
        }).OnUpdate()
}

And type argen or go generate on your command line.

Error
u := User{Name: "invalid name"}
_, errs := u.IsValid()
if errs != nil {
	fmt.Errorf("%v\n", errs.Messages["name"])
}

Log

LogMode(true)

go generate

If you want to generate it by using go generate, you mark it up an annotation at top of file.

//go:generate argen

and type:

$ go generate

Code status

Build Status

TODO

  • Transaction
  • Callbacks (before/after save)
  • Conditions for callbacks and validations.
  • AS clause
  • Log options

Author

monochromegane

License

argen is licensed under the MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsZero

func IsZero(v interface{}) bool

func ToCamelCase

func ToCamelCase(s string) string

Types

type Association

type Association struct {
	PrimaryKey string
	ForeignKey string
}

type CustomValidation

type CustomValidation func(errors *Errors)

type Delete

type Delete struct {
	*query.Delete
	// contains filtered or unexported fields
}

func NewDelete

func NewDelete(db *sql.DB, logger *Logger) *Delete

func (*Delete) And

func (d *Delete) And(cond string, args ...interface{}) *Delete

func (*Delete) Exec

func (d *Delete) Exec() (sql.Result, error)

func (*Delete) Table

func (d *Delete) Table(table string) *Delete

func (*Delete) Where

func (d *Delete) Where(cond string, args ...interface{}) *Delete

type Errors

type Errors struct {
	Messages map[string][]error
}

func (*Errors) Add

func (e *Errors) Add(field string, err string)

func (*Errors) AddError

func (e *Errors) AddError(field string, err error)

func (*Errors) Error

func (e *Errors) Error() string

func (*Errors) SetErrors

func (e *Errors) SetErrors(field string, errors []error)

type Executer

type Executer struct {
	// contains filtered or unexported fields
}

func (*Executer) Exec

func (e *Executer) Exec(q string, b ...interface{}) (sql.Result, error)

type Insert

type Insert struct {
	*query.Insert
	// contains filtered or unexported fields
}

func NewInsert

func NewInsert(db *sql.DB, logger *Logger) *Insert

func (*Insert) Exec

func (i *Insert) Exec() (sql.Result, error)

func (*Insert) Params

func (i *Insert) Params(params map[string]interface{}) *Insert

func (*Insert) Table

func (i *Insert) Table(table string) *Insert

type Logger

type Logger struct {
	*log.Logger
	LogMode bool
}

func (Logger) Print

func (l Logger) Print(values ...interface{})

type On

type On struct {
	// contains filtered or unexported fields
}

func OnCreate

func OnCreate() On

func OnUpdate

func OnUpdate() On

type Relation

type Relation struct {
	*query.Select
	// contains filtered or unexported fields
}

func NewRelation

func NewRelation(db *sql.DB, logger *Logger) *Relation

func (*Relation) And

func (r *Relation) And(cond string, args ...interface{}) *Relation

func (*Relation) Build

func (r *Relation) Build() (string, []interface{})

func (*Relation) Columns

func (r *Relation) Columns(columns ...string) *Relation

func (*Relation) Count

func (r *Relation) Count(column ...string) int

func (*Relation) Exists

func (r *Relation) Exists() bool

func (*Relation) Explain

func (r *Relation) Explain() error

func (*Relation) GetColumns

func (r *Relation) GetColumns() []string

func (*Relation) GroupBy

func (r *Relation) GroupBy(group string, groups ...string) *Relation

func (*Relation) Having

func (r *Relation) Having(cond string, args ...interface{}) *Relation

func (*Relation) Limit

func (r *Relation) Limit(limit int) *Relation

func (*Relation) Offset

func (r *Relation) Offset(offset int) *Relation

func (*Relation) OrderBy

func (r *Relation) OrderBy(column, order string) *Relation

func (*Relation) Query

func (r *Relation) Query() (*sql.Rows, error)

func (*Relation) QueryRow

func (r *Relation) QueryRow(dest ...interface{}) error

func (*Relation) Table

func (r *Relation) Table(table string) *Relation

func (*Relation) Where

func (r *Relation) Where(cond string, args ...interface{}) *Relation

type Rule

type Rule interface {
	Rule() *Validation
}

type Scope

type Scope struct {
	*Relation
	Args []interface{}
}

type Update

type Update struct {
	*query.Update
	// contains filtered or unexported fields
}

func NewUpdate

func NewUpdate(db *sql.DB, logger *Logger) *Update

func (*Update) And

func (u *Update) And(cond string, args ...interface{}) *Update

func (*Update) Exec

func (u *Update) Exec() (sql.Result, error)

func (*Update) Params

func (u *Update) Params(params map[string]interface{}) *Update

func (*Update) Table

func (u *Update) Table(table string) *Update

func (*Update) Where

func (u *Update) Where(cond string, args ...interface{}) *Update

type Validation

type Validation struct {
	// contains filtered or unexported fields
}

func CustomRule

func CustomRule(c CustomValidation) *Validation

func MakeRule

func MakeRule() *Validation

func (*Validation) CustomRule

func (v *Validation) CustomRule(c CustomValidation) *Validation

func (*Validation) Exclusion

func (v *Validation) Exclusion(collection ...string) *Validation

func (*Validation) Format

func (v *Validation) Format() *format

func (*Validation) Inclusion

func (v *Validation) Inclusion(collection ...string) *Validation

func (*Validation) Length

func (v *Validation) Length() *length

func (*Validation) Numericality

func (v *Validation) Numericality() *numericality

func (*Validation) OnCreate

func (v *Validation) OnCreate() *Validation

func (*Validation) OnSave

func (v *Validation) OnSave() *Validation

func (*Validation) OnUpdate

func (v *Validation) OnUpdate() *Validation

func (*Validation) Presence

func (v *Validation) Presence() *presence

func (*Validation) Rule

func (v *Validation) Rule() *Validation

type Validator

type Validator struct {
	// contains filtered or unexported fields
}

func NewValidator

func NewValidator(rule *Validation) Validator

func (Validator) Custom

func (v Validator) Custom() CustomValidation

func (Validator) IsValid

func (v Validator) IsValid(value interface{}) (bool, []error)

func (Validator) On

func (v Validator) On(on On) Validator

Directories

Path Synopsis
cmd
generated by argen; DO NOT EDIT generated by argen; DO NOT EDIT generated by argen; DO NOT EDIT generated by argen; DO NOT EDIT
generated by argen; DO NOT EDIT generated by argen; DO NOT EDIT generated by argen; DO NOT EDIT generated by argen; DO NOT EDIT

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL