So, sometimes the server uses Windows instead of Linux or BSD, and we need to execute certain command on the server, because the web interface not suffice, for example, exporting 1.2GB of data from MySQL using PHPMyAdmin? timeout! :3
We could use a tool called winexe, to install it, type:
yaourt -S winexe
Then just execute:
winexe -U USERNAME //IPADDRESS cmd.exe
Voila~ :3
programming: the action or process of writing computer programs. | rants: speak or shout at length in a wild, [im]passioned way.
2014-11-28
2014-11-27
How to use Go-Couchbase
Today I will try to use Go-Couchbase, to insert, fetch, update and delete from database. To install go-couchbase, type this commands:
go get -u -v github.com/couchbaselabs/go-couchbase
Then just create an example source code and run it:
package main
import (
"fmt"
"github.com/couchbaselabs/go-couchbase"
//"github.com/davecgh/go-spew/spew"
"encoding/json"
"github.com/kr/pretty"
//"reflect"
"errors"
"runtime"
"strings"
)
var FILE_PATH string
var CB *couchbase.Bucket
// initialize file path
func init() {
_, file, _, _ := runtime.Caller(1)
FILE_PATH = file[:4+strings.Index(file, "/src/")]
err := errors.New("no error")
CB, err = couchbase.GetBucket("http://127.0.0.1:8091/", "default", "default")
Panic(err, "Error connection, getting pool or bucket: %v")
}
// print warning message
func Check(err error, msg string, args ...interface{}) error {
if err != nil {
_, file, line, _ := runtime.Caller(1)
str := fmt.Sprintf("%s:%d: ", file[len(FILE_PATH):], line)
fmt.Errorf(str+msg, args...)
res := pretty.Formatter(err)
fmt.Errorf("%# v\n", res)
}
return err
}
// print error message and exit program
func Panic(err error, msg string, args ...interface{}) {
if Check(err, msg, args...) != nil {
panic(err)
}
}
// describe a variable
func Explain(args ...interface{}) {
_, file, line, _ := runtime.Caller(1)
//res, _ := json.MarshalIndent(variable, " ", " ")
for _, arg := range args {
res := pretty.Formatter(arg)
fmt.Printf("%s:%d: %# v\n", file[len(FILE_PATH):], line, res)
}
//spew.Dump(variable)
}
func main() {
var err error
// save values (upsert)
err = CB.Set("someKey", 0, []string{"an", "example", "list"})
Check(err, "failed to set somekey")
err = CB.Set("primaryKey", 0, 1)
Check(err, "failed to set primaryKey")
// fetch one value
var rv interface{}
err = CB.Get("someKey", &rv)
Check(err, "failed to get someKey")
Explain(rv)
// fetch with CheckAndSet id
cas := uint64(0)
err = CB.Gets("primaryKey", &rv, &cas)
Check(err, "failed to get primaryKey")
Explain(cas, rv)
// fetch multivalue
rows, err := CB.GetBulk([]string{"someKey", "primaryKey", "nothingKey"})
Check(err, "failed to get someKey or primaryKey or nothingKey")
Explain(rows)
jsonStr := rows["someKey"].Body
Explain(string(jsonStr))
stringList := []string{}
err = json.Unmarshal(jsonStr, &stringList)
Check(err, "failed to convert back to json")
Explain(stringList)
// increment value, returns new value
nv, err := CB.Incr("primaryKey", 1, 1, 0)
Check(err, "failed to increment primaryKey")
Explain(nv)
// increment value, defaults to 1 if not exists
nv, err = CB.Incr("key3", 1, 1, 60)
Check(err, "failed to increment primaryKey")
Explain(nv)
}
This would give an output:
go get -u -v github.com/couchbaselabs/go-couchbase
Then just create an example source code and run it:
package main
import (
"fmt"
"github.com/couchbaselabs/go-couchbase"
//"github.com/davecgh/go-spew/spew"
"encoding/json"
"github.com/kr/pretty"
//"reflect"
"errors"
"runtime"
"strings"
)
var FILE_PATH string
var CB *couchbase.Bucket
// initialize file path
func init() {
_, file, _, _ := runtime.Caller(1)
FILE_PATH = file[:4+strings.Index(file, "/src/")]
err := errors.New("no error")
CB, err = couchbase.GetBucket("http://127.0.0.1:8091/", "default", "default")
Panic(err, "Error connection, getting pool or bucket: %v")
}
// print warning message
func Check(err error, msg string, args ...interface{}) error {
if err != nil {
_, file, line, _ := runtime.Caller(1)
str := fmt.Sprintf("%s:%d: ", file[len(FILE_PATH):], line)
fmt.Errorf(str+msg, args...)
res := pretty.Formatter(err)
fmt.Errorf("%# v\n", res)
}
return err
}
// print error message and exit program
func Panic(err error, msg string, args ...interface{}) {
if Check(err, msg, args...) != nil {
panic(err)
}
}
// describe a variable
func Explain(args ...interface{}) {
_, file, line, _ := runtime.Caller(1)
//res, _ := json.MarshalIndent(variable, " ", " ")
for _, arg := range args {
res := pretty.Formatter(arg)
fmt.Printf("%s:%d: %# v\n", file[len(FILE_PATH):], line, res)
}
//spew.Dump(variable)
}
func main() {
var err error
// save values (upsert)
err = CB.Set("someKey", 0, []string{"an", "example", "list"})
Check(err, "failed to set somekey")
err = CB.Set("primaryKey", 0, 1)
Check(err, "failed to set primaryKey")
// fetch one value
var rv interface{}
err = CB.Get("someKey", &rv)
Check(err, "failed to get someKey")
Explain(rv)
// fetch with CheckAndSet id
cas := uint64(0)
err = CB.Gets("primaryKey", &rv, &cas)
Check(err, "failed to get primaryKey")
Explain(cas, rv)
// fetch multivalue
rows, err := CB.GetBulk([]string{"someKey", "primaryKey", "nothingKey"})
Check(err, "failed to get someKey or primaryKey or nothingKey")
Explain(rows)
jsonStr := rows["someKey"].Body
Explain(string(jsonStr))
stringList := []string{}
err = json.Unmarshal(jsonStr, &stringList)
Check(err, "failed to convert back to json")
Explain(stringList)
// increment value, returns new value
nv, err := CB.Incr("primaryKey", 1, 1, 0)
Check(err, "failed to increment primaryKey")
Explain(nv)
// increment value, defaults to 1 if not exists
nv, err = CB.Incr("key3", 1, 1, 60)
Check(err, "failed to increment primaryKey")
Explain(nv)
}
This would give an output:
/test.go:92: []interface {}{ "an", "example", "list", } /test.go:98: uint64(0x13aa8b32b9f7f091) /test.go:98: float64(1) /test.go:103: map[string]*gomemcached.MCResponse{ "primaryKey": &gomemcached.MCResponse{ Opcode: 0x0, Status: 0x0, Opaque: 0x0, Cas: 0x13aa8b32b9f7f091, Extras: {0x0, 0x0, 0x0, 0x0}, Key: {}, Body: {0x31}, Fatal: false, }, "someKey": &gomemcached.MCResponse{ Opcode: 0x0, Status: 0x0, Opaque: 0x0, Cas: 0x13aa8b32b9e4690f, Extras: {0x0, 0x0, 0x0, 0x0}, Key: {}, Body: {0x5b, 0x22, 0x61, 0x6e, 0x22, 0x2c, 0x22, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x22, 0x2c, 0x22, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x5d}, Fatal: false, }, } /test.go:106: "[\"an\",\"example\",\"list\"]" /test.go:111: []string{"an", "example", "list"} /test.go:116: uint64(0x2) /test.go:121: uint64(0x4)
How to install Couchbase on ArchLinux
Couchbase is NoSQL database with the best performance AFAIK. To install Couchbase, we need git and repo tool, that could be installed using this command:
sudo pacman -S git libtool gcc libevent make gperftools sqlite erlangautomake autoconf make curl dmidecode
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod +x ~/bin/repo
Change first line from python to python2.7, then initialize and start fetch the Couchbase repository:
mkdir couchbase
cd couchbase
repo init -u git://github.com/couchbase/manifest.git -m released/3.0.1.xml
repo snyc
To prevent failure when building python-based programs, symlink your python to the older one:
sudo ln -sf python2.7 /usr/bin/python
Install older version of v8 (3.21.17 or less), using this command:
yaourt -S v8-3.15
V8PKG=v8-3.19.18.4-1-x86_64.pkg.tar.xz
wget http://seblu.net/a/arm/packages/v/v8/$V8PKG
sudo pacman -U $V8PKG
Then compile the Couchbase:
make
Note if this step failed clean the couchbase first using make clean, then compile the v8 on the v8 folder in the couchbase directory. If you're using latest version of GCC, remove all werror string from build/standalone.gypi and build/toolchain.gpyi file:
make dependencies
export PYTHON=python2
find build/ test/ tools/ src/ -type f \
-exec sed -e 's_^#!/usr/bin/env python$_&2_' \
-e 's_^\(#!/usr/bin/python2\).[45]$_\1_' \
-e 's_^#!/usr/bin/python$_&2_' \
-e "s_'python'_'python2'_" -i {} \;
sed -i 's/python /python2 /' Makefile
sed -i 's/-Werror//' build/standalone.gypi build/common.gypi
make x64.release library=shared console=readline
Alternatively use this modified PKGBUILD file:
wget http://goo.gl/miEmFt -O PKGBUILD
makepkg
sudo pacman -U v8-3.21-3.21.17-1-x86_64.pkg.tar.xz
Don't forget to increase the default number of files:
echo '
* soft nofile 65536
* hard nofile 65536
' | sudo tee -a /etc/security/limits.conf
And last, start the server:
./install/bin/couchbase-server
Then just visit the web interface to setup the cluster http://localhost:8091/
That's it, that's how you install Couchbase on ArchLinux from source.
sudo pacman -S git libtool gcc libevent make gperftools sqlite erlangautomake autoconf make curl dmidecode
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod +x ~/bin/repo
Change first line from python to python2.7, then initialize and start fetch the Couchbase repository:
mkdir couchbase
cd couchbase
repo init -u git://github.com/couchbase/manifest.git -m released/3.0.1.xml
repo snyc
To prevent failure when building python-based programs, symlink your python to the older one:
sudo ln -sf python2.7 /usr/bin/python
Install older version of v8 (3.21.17 or less), using this command:
yaourt -S v8-3.15
V8PKG=v8-3.19.18.4-1-x86_64.pkg.tar.xz
wget http://seblu.net/a/arm/packages/v/v8/$V8PKG
sudo pacman -U $V8PKG
Then compile the Couchbase:
make
Note if this step failed clean the couchbase first using make clean, then compile the v8 on the v8 folder in the couchbase directory. If you're using latest version of GCC, remove all werror string from build/standalone.gypi and build/toolchain.gpyi file:
make dependencies
export PYTHON=python2
find build/ test/ tools/ src/ -type f \
-exec sed -e 's_^#!/usr/bin/env python$_&2_' \
-e 's_^\(#!/usr/bin/python2\).[45]$_\1_' \
-e 's_^#!/usr/bin/python$_&2_' \
-e "s_'python'_'python2'_" -i {} \;
sed -i 's/python /python2 /' Makefile
sed -i 's/-Werror//' build/standalone.gypi build/common.gypi
make x64.release library=shared console=readline
Alternatively use this modified PKGBUILD file:
wget http://goo.gl/miEmFt -O PKGBUILD
makepkg
sudo pacman -U v8-3.21-3.21.17-1-x86_64.pkg.tar.xz
Don't forget to increase the default number of files:
echo '
* soft nofile 65536
* hard nofile 65536
' | sudo tee -a /etc/security/limits.conf
And last, start the server:
./install/bin/couchbase-server
Then just visit the web interface to setup the cluster http://localhost:8091/
That's it, that's how you install Couchbase on ArchLinux from source.
2014-11-26
How to start Martini Golang Project
Martini is another Golang web framework, that the design similar to Sinatra, to install it, just type this command:
go get -u -v github.com/go-martini/martini
Then, just create new source code, for example main.go:
package main
import "github.com/go-martini/martini"
func main() {
m := martini.Classic()
m.Get("/", func() string {
return "Hello world!"
})
m.Run()
}
To run the website, just type:
go run main.go
Then visit http://localhost:3000/
We must recompile the source everytime the source code changed, that quite annoying and time consuming, to overcome that problem we could use a tool called gin, this program automatically run a program everytime there are code changed. To install this tool, type:
go get -u -v github.com/codegangsta/gin
Then run it using this command:
gin go run main.go
That command would create a proxy, if there are compilation errors, it would also show on the page.
go get -u -v github.com/go-martini/martini
Then, just create new source code, for example main.go:
package main
import "github.com/go-martini/martini"
func main() {
m := martini.Classic()
m.Get("/", func() string {
return "Hello world!"
})
m.Run()
}
To run the website, just type:
go run main.go
We must recompile the source everytime the source code changed, that quite annoying and time consuming, to overcome that problem we could use a tool called gin, this program automatically run a program everytime there are code changed. To install this tool, type:
go get -u -v github.com/codegangsta/gin
Then run it using this command:
gin go run main.go
That command would create a proxy, if there are compilation errors, it would also show on the page.
How to install Goclipse and Golang IDEA plugin
Warning: current master version of these plugins (2014-11-25) are not good enough for daily coding, don't bother to try them for now.
Edit: latest alpha version of Golang IDEA plugin for IntelliJ are the best plugin for now.
Goclipse is another IDE for golang, that based on the infamous Eclipse platform. To install Eclipse, just type:
pacman -S eclipse
To install Goclipse, you must first clone the repository, for example using this command:
git clone --depth 1 https://github.com/GoClipse/goclipse.git
Then you must download all dependencies and start building:
cd goclipse
mvn clean integration-test
ant -f releng/ CreateProjectSite
ant -f releng/ PublishProjectSite
Last command would fail when not supplied with correct DprojectSiteGitURL parameter, but the required jars still resides in bin-maven/projectSite/, just use any webserver to serve the files as Eclipse update site, for example using php:
cd bin-maven/projectSite/
php -S localhost:9009
To install Goclipse, open Eclipse, Help > Install New Software.., just add http://localhost:9009/releases
Then select Goclipse, next, accept the license, and finish.
Now the bad parts: bad coloring (for example, the operator color is not configurable), gocode doesn't work (even when GOPATH and GOROOT already configured on settings page and restarted), and autocomplete doesn't work at all.
Next we'll try IntelliJ with Golang IDEA plugin, first you must clone the repository:
git clone --depth 1 https://github.com/go-lang-plugin-org/go-lang-idea-plugin.git
Then place (or symlink) the IntelliJ program directory inside that folder that created by git, with name idea-IC, then just run:
ant -f build-package.xml
That command would produce a file named: google-go-language.jar, just install that plugin normally using on IntelliJ.
Now the bad parts: member autocomplete doesn't work at all (even when GOROOT and GOPATH configured on settings page and restarted).
Edit: latest alpha version of Golang IDEA plugin for IntelliJ are the best plugin for now.
Goclipse is another IDE for golang, that based on the infamous Eclipse platform. To install Eclipse, just type:
pacman -S eclipse
To install Goclipse, you must first clone the repository, for example using this command:
git clone --depth 1 https://github.com/GoClipse/goclipse.git
Then you must download all dependencies and start building:
cd goclipse
mvn clean integration-test
ant -f releng/ CreateProjectSite
ant -f releng/ PublishProjectSite
Last command would fail when not supplied with correct DprojectSiteGitURL parameter, but the required jars still resides in bin-maven/projectSite/, just use any webserver to serve the files as Eclipse update site, for example using php:
cd bin-maven/projectSite/
php -S localhost:9009
To install Goclipse, open Eclipse, Help > Install New Software.., just add http://localhost:9009/releases
Then select Goclipse, next, accept the license, and finish.
Now the bad parts: bad coloring (for example, the operator color is not configurable), gocode doesn't work (even when GOPATH and GOROOT already configured on settings page and restarted), and autocomplete doesn't work at all.
Next we'll try IntelliJ with Golang IDEA plugin, first you must clone the repository:
git clone --depth 1 https://github.com/go-lang-plugin-org/go-lang-idea-plugin.git
Then place (or symlink) the IntelliJ program directory inside that folder that created by git, with name idea-IC, then just run:
ant -f build-package.xml
That command would produce a file named: google-go-language.jar, just install that plugin normally using on IntelliJ.
Now the bad parts: member autocomplete doesn't work at all (even when GOROOT and GOPATH configured on settings page and restarted).
2014-11-25
Wide: Web-based IDE for Go
Wide is one new web-based IDE, it has a lot of potential, for now, it has autocomplete and one that have working "go to definition".
To install Wide, type:
go get -u -v github.com/88250/ide_stub
go get -u -v github.com/nsf/gocode
go get -u -v github.com/b3log/wide
To start the program, type:
cd $GOPATH/src/github.com/b3log/wide/
wide
Then visit using your browser on http://your_ip_address:7070
To install Wide, type:
go get -u -v github.com/88250/ide_stub
go get -u -v github.com/nsf/gocode
go get -u -v github.com/b3log/wide
To start the program, type:
cd $GOPATH/src/github.com/b3log/wide/
wide
Then visit using your browser on http://your_ip_address:7070
There are some other web-based IDE such as GoDev (lags when showing godoc), LimeText, Carpo, Atom (aur/atom-editor-bin), Brackets.io, and Conception-go (this one not a web-based :3 it's OpenGL)
Btw, I make a list on GoogleDocs to list all Go IDEs, you can contribute/edit it if you want..
2014-11-24
Database GUI for MongoDB
There are many database GUI for MongoDB, today I will review about GenghisApp, Humongous, and RoboMongo.
You could install the Ruby-based one using this command:
gem install humongous
gem install genghisapp bson_ext
to start it, use this command:
humongous # visit http://localhost:9000
genghisapp # visit http://localhost:8000
php -S localhost:8000 genghis.php # php version
to stop it, use this command:
humongous -K
genghisapp --kill
I don't know why but when I tried both, they are not running at all, just stopped after showing "trying port xxxx", those programs closes immediately after that, the program doesn't show up on ps and netstat.
The next in line is RoboMongo, first, you must download using this command:
wget -c http://robomongo.org/files/linux/robomongo-0.8.4-x86_64.tar.gz
Extract it, then run the robomongo.sh shell script on the bin/ folder, set the connection, then it would show up something like this:
This one quote good, it shows the command line when doing any action, but as usual, Java-based app doesn't work well with dark GTK+ theme.
There are some other GUI for MongoDB that support live-monitoring, for example MongoBird and MongOwl, but don't forget, there are also built-in web monitoring on port 28017.
You could install the Ruby-based one using this command:
gem install humongous
gem install genghisapp bson_ext
to start it, use this command:
humongous # visit http://localhost:9000
genghisapp # visit http://localhost:8000
php -S localhost:8000 genghis.php # php version
to stop it, use this command:
humongous -K
genghisapp --kill
I don't know why but when I tried both, they are not running at all, just stopped after showing "trying port xxxx", those programs closes immediately after that, the program doesn't show up on ps and netstat.
The next in line is RoboMongo, first, you must download using this command:
wget -c http://robomongo.org/files/linux/robomongo-0.8.4-x86_64.tar.gz
Extract it, then run the robomongo.sh shell script on the bin/ folder, set the connection, then it would show up something like this:
This one quote good, it shows the command line when doing any action, but as usual, Java-based app doesn't work well with dark GTK+ theme.
There are some other GUI for MongoDB that support live-monitoring, for example MongoBird and MongOwl, but don't forget, there are also built-in web monitoring on port 28017.
2014-11-15
How to Prevent ISP's DNS Poisoning
The case was, my fourth ISP redirect every DNS request to their own DNS servers, and the poison certain domain names (for example: Manga sites) to their own server (114.127.223.16). How to prevent this? first of all you'll need to install dnscrypt, this program could encrypt DNS requests, so it's become harder to poison.
pacman -Sy dnscrpyt-proxy
then you'll need to start the service:
sudo systemctl enable dnscrypt-proxy
sudo systemctl start dnscrypt-proxy
then, change your /etc/resolv.conf to localhost:
nameserver 127.0.0.1
voila, now your DNS resolving not poisoned anymore :3 yayy~
pacman -Sy dnscrpyt-proxy
then you'll need to start the service:
sudo systemctl enable dnscrypt-proxy
sudo systemctl start dnscrypt-proxy
then, change your /etc/resolv.conf to localhost:
nameserver 127.0.0.1
voila, now your DNS resolving not poisoned anymore :3 yayy~
2014-11-04
How to start Revel, GORM with PostgreSQL project on Archlinux
Revel is one of many Go Web Application Framework that uses Go programming language. After installing Archlinux, first of all you'll need to install yaourt, the easiest way to install AUR packages. After that you'll need to run this command:
yaourt -Sy --noconfirm go postgresql postgresql-libs liteide chromium google-chrome-stable
Then setup your GOPATH and GOROOT environment variables on your .bashrc
export GOROOT=/usr/lib/go
export GOPATH=$HOME/Dropbox/go
export PATH="$PATH:$GOPATH/bin"
Change the permission of this folder:
sudo chmod -Rv a+rwx /usr/share/liteide/liteenv
Then open LiteIDE, select menu View > Edit Environment, then add this line and save:
GOROOT=/usr/lib/go
Add also a GOPATH directory on menu View > Manage GOPATH...
That is ~/Dropbox/go on my computer.
To test if your Go and LiteIDE working correctly, create a new .go file and press Build > FileRun to run, for example:
package main
import "fmt"
func main() {
fmt.Println("Hello my PC <3")
}
The code above should give an output on Build output window.
To install revel, type this on shell:
go get -u -v github.com/revel/cmd/revel
go get -u -v github.com/revel/revel
To create a new project (for example, the name would be "puis"), type:
cd $GOPATH
revel new puis
Then you could start the app using this command:
revel run puis
And visit http://localhost:9000 to view your app.
Next, we should install PostgreSQL driver and GORM, type:
go get -u -v github.com/lib/pq
go get -u -v github.com/jinzhu/gorm
Then initialize and start your database server:
sudo su - postgres
initdb --locale en_US.UTF-8 -E UTF8 -D '/var/lib/postgres/data'
exit
sudo systemctl enable postgresql
sudo systemctl start postgresql
sudo su - postgres
createuser puis
createdb puis
psql
GRANT ALL PRIVILEGES ON DATABASE puis TO puis;
\q
exit
Then create a model, for example in app/models/user.go
package models
import "time"
type User struct {
Id int64
Name string
Gmail string
PuMail string
Password string
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt time.Time
LastLoginAt time.Time
PasswordUpdatedAt time.Time
}
And create a controller for GORM in app/controllers/gorm.go
package controllers
import (
"database/sql"
"github.com/jinzhu/gorm"
_ "github.com/lib/pq"
"github.com/revel/revel"
"puis/app/models"
)
type GormController struct {
*revel.Controller
Tx *gorm.DB
}
var Db gorm.DB
func InitDB() {
var err error
Db, err = gorm.Open("postgres", "user=puis sslmode=disable")
if err != nil {
revel.ERROR.Println("FATAL", err)
panic(err)
}
tab := &models.User{}
Db.AutoMigrate(tab)
Db.Model(tab).AddUniqueIndex("idx_user__gmail", "gmail")
Db.Model(tab).AddUniqueIndex("idx_user__pu_mail", "pu_mail")
}
func (c *GormController) Begin() revel.Result {
txn := Db.Begin()
if txn.Error != nil {
panic(txn.Error)
}
c.Tx = txn
revel.INFO.Println("c.Tx init", c.Tx)
return nil
}
func (c *GormController) Commit() revel.Result {
if c.Tx == nil {
return nil
}
c.Tx.Commit()
if err := c.Tx.Error; err != nil && err != sql.ErrTxDone {
panic(err)
}
c.Tx = nil
revel.INFO.Println("c.Tx commited (nil)")
return nil
}
func (c *GormController) Rollback() revel.Result {
if c.Tx == nil {
return nil
}
c.Tx.Rollback()
if err := c.Tx.Error; err != nil && err != sql.ErrTxDone {
panic(err)
}
c.Tx = nil
return nil
}
Also call those functions when application starts also before and after controller calling, add these lines in app/init.go on func init()
revel.OnAppStart(controllers.InitDB)
revel.InterceptMethod((*controllers.GormController).Begin, revel.BEFORE)
revel.InterceptMethod((*controllers.GormController).Commit, revel.AFTER)
revel.InterceptMethod((*controllers.GormController).Rollback, revel.FINALLY)
Two more things, add a testing code, for example in app/controllers/app.go on func Index()
user := &models.User{Name: "Kiswono Prayogo"}
c.Tx.NewRecord(user)
c.Tx.Create(user)
return c.Render(user)
Last thing, just add one more line anywhere on Index.html
{{.user.Name}}
That's it, this is how to connect Revel to PostgreSQL using GORM. This tutorial adapted from Ivan Black's stackoverflow answer.
To solve slow Revel hot-reload or Go build/install, just use this command:
go get -u -v github.com/mattn/go-sqlite3
yaourt -Sy --noconfirm go postgresql postgresql-libs liteide chromium google-chrome-stable
Then setup your GOPATH and GOROOT environment variables on your .bashrc
export GOROOT=/usr/lib/go
export GOPATH=$HOME/Dropbox/go
export PATH="$PATH:$GOPATH/bin"
Change the permission of this folder:
sudo chmod -Rv a+rwx /usr/share/liteide/liteenv
Then open LiteIDE, select menu View > Edit Environment, then add this line and save:
GOROOT=/usr/lib/go
Add also a GOPATH directory on menu View > Manage GOPATH...
That is ~/Dropbox/go on my computer.
To test if your Go and LiteIDE working correctly, create a new .go file and press Build > FileRun to run, for example:
package main
import "fmt"
func main() {
fmt.Println("Hello my PC <3")
}
The code above should give an output on Build output window.
To install revel, type this on shell:
go get -u -v github.com/revel/cmd/revel
go get -u -v github.com/revel/revel
To create a new project (for example, the name would be "puis"), type:
cd $GOPATH
revel new puis
Then you could start the app using this command:
revel run puis
And visit http://localhost:9000 to view your app.
Next, we should install PostgreSQL driver and GORM, type:
go get -u -v github.com/lib/pq
go get -u -v github.com/jinzhu/gorm
Then initialize and start your database server:
sudo su - postgres
initdb --locale en_US.UTF-8 -E UTF8 -D '/var/lib/postgres/data'
exit
sudo systemctl enable postgresql
sudo systemctl start postgresql
sudo su - postgres
createuser puis
createdb puis
psql
GRANT ALL PRIVILEGES ON DATABASE puis TO puis;
\q
exit
Then create a model, for example in app/models/user.go
package models
import "time"
type User struct {
Id int64
Name string
Gmail string
PuMail string
Password string
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt time.Time
LastLoginAt time.Time
PasswordUpdatedAt time.Time
}
package controllers
import (
"database/sql"
"github.com/jinzhu/gorm"
_ "github.com/lib/pq"
"github.com/revel/revel"
"puis/app/models"
)
type GormController struct {
*revel.Controller
Tx *gorm.DB
}
var Db gorm.DB
func InitDB() {
var err error
Db, err = gorm.Open("postgres", "user=puis sslmode=disable")
if err != nil {
revel.ERROR.Println("FATAL", err)
panic(err)
}
tab := &models.User{}
Db.AutoMigrate(tab)
Db.Model(tab).AddUniqueIndex("idx_user__gmail", "gmail")
Db.Model(tab).AddUniqueIndex("idx_user__pu_mail", "pu_mail")
}
func (c *GormController) Begin() revel.Result {
txn := Db.Begin()
if txn.Error != nil {
panic(txn.Error)
}
c.Tx = txn
revel.INFO.Println("c.Tx init", c.Tx)
return nil
}
func (c *GormController) Commit() revel.Result {
if c.Tx == nil {
return nil
}
c.Tx.Commit()
if err := c.Tx.Error; err != nil && err != sql.ErrTxDone {
panic(err)
}
c.Tx = nil
revel.INFO.Println("c.Tx commited (nil)")
return nil
}
func (c *GormController) Rollback() revel.Result {
if c.Tx == nil {
return nil
}
c.Tx.Rollback()
if err := c.Tx.Error; err != nil && err != sql.ErrTxDone {
panic(err)
}
c.Tx = nil
return nil
}
Also call those functions when application starts also before and after controller calling, add these lines in app/init.go on func init()
revel.OnAppStart(controllers.InitDB)
revel.InterceptMethod((*controllers.GormController).Begin, revel.BEFORE)
revel.InterceptMethod((*controllers.GormController).Commit, revel.AFTER)
revel.InterceptMethod((*controllers.GormController).Rollback, revel.FINALLY)
Two more things, add a testing code, for example in app/controllers/app.go on func Index()
user := &models.User{Name: "Kiswono Prayogo"}
c.Tx.NewRecord(user)
c.Tx.Create(user)
return c.Render(user)
Last thing, just add one more line anywhere on Index.html
{{.user.Name}}
That's it, this is how to connect Revel to PostgreSQL using GORM. This tutorial adapted from Ivan Black's stackoverflow answer.
To solve slow Revel hot-reload or Go build/install, just use this command:
go get -u -v github.com/mattn/go-sqlite3