Golang Gorm error migrating struct - mysql

I have a small mistake in my small application and I really do not see where it can come from. So I have 4 structs, one of the 4 struct has several one-to-one relationships.
I connect to my database and use automigrate to migrate my 4 structs and create the necessary tables.
The problem is at this point, it does not create anything in the database and in the terminal I have this message:
(Error 1060: Name of the 'id' field already in use)
My code
main.go
package main
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
var db *gorm.DB
var err error
const (
mysupersecretpassword = "cr9ih_pvr9f9kc75n#bz&y%(#+^&1_#hr0^)-$kv%n3dh84$^w"
)
func main() {
db, err = gorm.Open("mysql", "root:root#/test?charset=utf8&parseTime=True")
if err != nil {
fmt.Println(err)
}
defer db.Close()
db.AutoMigrate(&User{}, &Ads{}, &Type{}, &Category{}, &Location{})
}
models.go
package main
import (
"github.com/jinzhu/gorm"
)
type User struct {
gorm.Model
Username string `json:"username"`
Email string `json:"email" form:"email"`
Password string `json:"password" form:"password"`
active bool `json:"active" gorm:"default:0"`
level bool `json:"level" gorm:"default:0"`
}
type Type struct {
gorm.Model
Name string `json:"name" form:"name"`
}
type Category struct {
gorm.Model
CatID uint `json:"category-parent" form:"category-parent" gorm:"default:0"`
Name string `json:"name" form:"name"`
}
type Location struct {
gorm.Model
Location string `json:"location" form:"location"`
}
type Ads struct {
gorm.Model
User User `json:"user"`
Type Type `json:"type" form:"type"`
Category Category `json:"category" form:"category"`
Title string `json:"title" form:"title"`
Content string `json:"content" form:"content"`
Location Location `json:"location" form:"location"`
}
Waiting for an answer that could put me on the right path :)

AutoMigrate will ONLY create tables, missing columns and missing indexes, and WON'T change existing column's type or delete unused columns to protect your data.
I would guess that one of your tables already exists, and the id column in that table is a different type than what gorm.Model wants to create. I would figure out which table it is by doing:
db.AutoMigrate(&User{})
db.AutoMigrate(&Ads{})
db.AutoMigrate(&Type{})
db.AutoMigrate(&Category{})
db.AutoMigrate(&Location{})
and seeing where it fails. Then, I would backup that table (just in case), and then either just drop the table completely, or rename the id column to tmp_id, see if automigrate fixes it, and if so, drop the tmp_id column.

FYI I've found Gorm will not log proper error or any error if it has permission issues on the user. For example the table existed when logged in as root, but the user I was logging in as didn't see it at all, Gorm just ran through Migration without creating the table or altering it (even though it was different schema) just didn't report any permission issue at all.

Related

Proper way to create MySql interface in Go

I am working on connecting my application to MySql. The code is structured the following way, which works, but looks a little odd to me. Is this the right pattern to follow?
I have saved my Db related things in a separate file, which looks like this:
var DatabaseObject MySqlDatabase
type IMySqlDatabase interface {
ConnectToDb() MySqlDatabase
GetDb() MySqlDatabase
}
type MySqlDatabase struct{
Db *sql.DB
}
func (MySqlDatabase) ConnectToDb(connectionString string){
db, _ := sql.Open("mysql", connectionString)
_ = db.Ping()
DatabaseObject = MySqlDatabase{Db: db}
}
func (MySqlDatabase) GetDb() *sql.DB{
return DatabaseObject.Db
}
As such I can connect to the database the following way:
infrastructureMySql.DatabaseObject.ConnectToDb(connectionString)
Which I find odd. Is there any sense of having an interface in the first place? If I didn't have it I could simply use the *sql.DB as a global variable. Thank you for your feedback.
I generally like to follow this guide by Ben Johnson when creating db:
See 3. Wrap types for application-specific context
This article mentions that we can provide an abstract layer here by interacting with the interface and so you don't need to leak these details in the application layer.
You mentioned that you would like to perform queries and other commands so you can draw up an interface regarding those commands like so:
type Mysql struct {
db *sql.DB
}
// Wrap a new connection into the MySql struct
func NewMysql() (*Mysql, error) {
db, err := sql.Open(...)
return &Mysql{ db }, err
}
func (m *Mysql) GetUsers(...) ([]User, error) {}
func (m *Mysql) CreateUsers(...) (User, error) {}
type UserStore interface {
GetUsers func(...) []User, error)
CreateUsers func(...) (User, error)
}
This is definitely incorrect:
MySqlDatabase does not implement IMySqlDatabase, so it would not work if you actually tried to use the interface
You're not actually using the interface
And has style issues:
The interface returns concrete types, which defeats the purpose
The interface appears to be a factory of itself? Or something? It's unclear what the interface or the concrete type are really supposed to be/do
Interfaces in Go should not be named IThing, that's C#
You appear to have type methods which modify globals which is going to be extremely unexpected to anyone using them

golang - elegant way to omit a json property from being serialized

I've got a user struct, which has sensitive fields like password:
type User struct {
UID string `json:"uid" binding:"required"`
Password string `json:"password" binding:"required"`
EmailAddress string `json:"email" binding:"required"`
}
Now I want to be able to use this struct to register a user and update, delete but also to view. What I don't want is for the password to be serialized for viewing. I can, of course, make a custom marshaller but is that the only way? I tried using the json:"-" option but that causes it to be ignored while unmarshalling as well, which I don't want. Is there a better way?
EDIT:
To put some of you guys at ease, I'm NOT going to be storing the password in plaintext, of course. It's the bcrypt hash of the password, but still. I don't want it to be returned when I search for users.
I'd say implementing json.Marshaler is the elegant solution if you want custom marshaling. It's quite simple in this case:
func (u User) MarshalJSON() ([]byte, error) {
type user User // prevent recursion
x := user(u)
x.Password = ""
return json.Marshal(x)
}
Add "omitempty" in your User type if you don't want the password field at all when marshaling.
I would go with another struct and composition.
Password should never be stored in plain-text, they should be securely hashed (bcrypt, pbkdf2, etc.). That hash is the one that has to be stored and should never be serialized. By using composition, you can do something like this:
type User struct {
UID string `json:"uid" binding:"required"`
HashedPassword string `json:"-"`
EmailAddress string `json:"email" binding:"required"`
}
type UserFormData struct {
User
Password string `json:"password" binding:"required"`
}
This also gives you more flexibility. For instance, if you ask the user to confirm the password, you can simply change the UserFormData struct like this:
type UserFormData struct {
User
Password string `json:"password" binding:"required"`
ConfirmPassword string `json:"confirm_password" binding:"required"`
}
Which also has the advantage to keep that serialization details outside your User object.
A simple solution would be to sanitize the user struct before marshaling it:
type User struct {
UID string `json:"uid" binding:"required"`
Password string `json:"password,omitempty" binding:"required"`
EmailAddress string `json:"email" binding:"required"`
}
func sanitizeUser(u User) User {
return User{u.UID, "", u.EmailAddress}
}
Demo: https://play.golang.org/p/RjKVoFc9o8
Now I want to be able to use this struct to register a user and update, delete but also to view.
Another solution is not to store the password at all in the struct. You don't need it to view, or delete, or update (normally).
You need it to create the user record, at which point you'll store a hash in your data store.
You need it to verify their identity (on login), at which point you verify against the hash in your data store, then usually issue a token they can use to keep accessing the service.
So there are only a few points you need it, and at those points you can simply keep it in memory separately and verify identity, it doesn't need to be exposed or stored in the struct for most operations. This is IMO more elegant than having it in the struct where it can very easily be exposed by mistake in export or logging.
You can query the database with a select statement to get only fields you like.
db.Model(&User{}).Select([]string{"uid","email"}).Find(&users)
Also add omitempty in your User type since empty response is sent for fields not included in select.

One to One relation mapping using GORM for Golang

I am trying to understand how GORM works for one to one relational mapping with MySQL. I have 2 structs like so:
type User struct {
Id uint `gorm:"AUTO_INCREMENT"`
FirstName string `gorm:"column:first_name"`
LastName string `gorm:"column:last_name"`
EncryptedUserId string `gorm:"size:255"`
Email string `gorm:"not null;unique"`
Password string `gorm:"not null;unique"`
CreatedAt int64 `gorm:"type(timestamp)"`
}
type UserSession struct {
Id uint `gorm:"AUTO_INCREMENT"`
UserId User
SessionToken string `gorm:"column:session_token"`
CreatedAt int64 `gorm:"type(timestamp)"`
}
User and UserSession share one to one relation. But when code above is run, the column UserId for UserSession table is not created. Even after specifying the foreign key constraint gorm:"ForeignKey:Id"
the result is same. Why isn't the above code working? Is anything missing in the struct definition?
I can't comment your questions so I would ask it here:
Do you migrate your schema in any way like:
db.AutoMigrate(&User{}, &UserSession{})
?
If you do, you should get some detailed errors in log, which might be useful for you.
The way I have managed to get something similar to work is this.
type UserSession struct {
Id uint `gorm:"AUTO_INCREMENT"`
UserId uint
User User
SessionToken string `gorm:"column:session_token"`
CreatedAt int64 `gorm:"type(timestamp)"`
}

Override struct tags in go

I have an entity in my project that is viewable by public and by admin. Not all fields should be accessible by public.
For example
type Foo struct {
Id bson.ObjectId `json:"id" bson:"_id"`
DateAdded time.Time `json:"date_added" bson:"date_added"`
Bar string `json:"bar" bson:"bar"`
AdminOnly string `json:"admin_only" bson:"admin_only"`
}
AdminOnly field should be only visible to admins.
For now, when requests comes from public, I call separate method that copies every needed field to new struct
type FooPublic struct {
Id bson.ObjectId `json:"id" bson:"_id"`
DateAdded time.Time `json:"date_added" bson:"date_added"`
Bar string `json:"bar" bson:"bar"`
}
func (f *Foo) Public() (res FooPublic) {
res = FooPublic{
Id: f.Id,
DateAdded: f.DateAdded,
Bar:f.Bar,
}
return
}
But if I need to add new field to my entity, I need to add it in 3 places. In struct itself, in PublicFoo and in Public method.
This seems to be agains DRY principle. What is correct, idiomatic solution here? Can I define FooPublic so it overrides tags of needed fields? Or probably there is at least good way to copy corresponding fields from one struct to another, so I don't need to do this manually in Public method?
In general this repetition can be avoided by using embedding. Your Foo type should embed FooPublic:
type FooPublic struct {
Id bson.ObjectId `json:"id" bson:"_id"`
DateAdded time.Time `json:"date_added" bson:"date_added"`
Bar string `json:"bar" bson:"bar"`
}
type Foo struct {
FooPublic
AdminOnly string `json:"admin_only" bson:"admin_only"`
}
func (f *Foo) Public() FooPublic {
return f.FooPublic
}
But if someone is able to call the Foo.Public(), that someone already has the Foo or *Foo value (and so can access the exported AdminOnly field), so what's the point?
A better solution would be to use an interface, and not expose the Foo struct.

One struct with multiple json representations

The problem I'm trying to solve is that I have a model of a community that looks like this
type Community struct {
Name string
Description string
Sources []Source
Popularity int
FavoriteCount int
Moderators []string
Children []Community
Tracks []Track
}
Communities hold a lot of information and there are scenarios when I want to return only part of the description such as if I'm returning a list of trending communities. In this case I'd want to return only
type Community struct {
Name string
Description string
Popularity int
FavoriteCount int
}
The only way I can think of doing this is to create a new type containing only those fields and write a convenience method that takes a community and returns that type, but essentially creating a new object and copying those fields by value, is there a better way to do this?
I'm aware of the json:"-" syntax, but I'm not sure of how you could do this on a case by case basis as I still need to sometimes return the full object, perhaps a different type that is converted to?
[This](http://attilaolah.eu/2014/09/10/json-and-struct-composition-in-go/
) is a cool approach, which involves creating a sort of Masking struct.
Here's the example in the article:
type User struct {
Email string `json:"email"`
Password string `json:"password"`
// many more fields…
}
type omit *struct{}
type PublicUser struct {
*User
Password omit `json:"password,omitempty"`
}
// when you want to encode your user:
json.Marshal(PublicUser{
User: user,
})
I developed a library which can help you in this regard: Sheriff
You can annotate your struct fields with special tags and call Sheriff to transform the given struct into a subset of it. After that you can call json.Marshal() or whatever else you want to marshal into.
Your example would become as simple as:
type Community struct {
Name string `json:"name" groups:"trending,detail"`
Description string `json:"description" groups:"trending,detail"`
Sources []Source `json:"sources" groups:"detail"`
Popularity int `json:"popularity" groups:"trending,detail"`
FavoriteCount int `json:"favorite_count" groups:"trending,detail"`
Moderators []string `json:"moderators" groups:"detail"`
Children []Community `json:"children" groups:"detail"`
Tracks []Track `json:"tracks" groups:"detail"`
}
communities := []Community{
// communities
}
o := sheriff.Options{
Groups: []string{"trending"},
}
d, err := sheriff.Marshal(&o, communities)
if err != nil {
panic(err)
}
out, _ := json.Marshal(d)
Yep that is the only way as far as I know using the default marshaler. The only other option is if you create your own json.Marshaler .
type Community struct {
}
type CommunityShort Community
func (key *Community) MarshalJSON() ([]byte, os.Error) {
...
}
func (key *Community) UnmarshalJSON(data []byte) os.Error {
...
}
func (key *CommunityShort) MarshalJSON() ([]byte, os.Error) {
...
}
func (key *CommunityShort) UnmarshalJSON(data []byte) os.Error {
...
}
I'll present you another approach that I've developed. I think it's much more clean. The only downside is slightly complicated object initialization, but in usage it's very streamlined.
The main point is that you're not basing your JSON-view-object on the original object and then hiding elements in it, but the other way around, making it a part of the original object:
type CommunityBase struct {
Name string
Description string
}
type Community struct {
CommunityBase
FavoriteCount int
Moderators []string
}
var comm = Community{CommunityBase{"Name", "Descr"}, 20, []string{"Mod1","Mod2"}}
json.Marshal(comm)
//{"Name":"Name","Description":"Descr","FavoriteCount":20,"Moderators":["Mod1","Mod2"]}
json.Marshal(comm.CommunityBase)
//{"Name":"Name","Description":"Descr"}
And that's all if you need only one view, or if your views are gradually expanded.
But if your views can't be inherited, you'll have to resort to a kind of mixins, so you can make a combined view from them:
type ThingBaseMixin struct {
Name string
}
type ThingVisualMixin struct {
Color string
IsRound bool
}
type ThingTactileMixin struct {
IsSoft bool
}
type Thing struct {
ThingBaseMixin
ThingVisualMixin
ThingTactileMixin
Condition string
visualView *ThingVisualView
tactileView *ThingTactileView
}
type ThingVisualView struct {
*ThingBaseMixin
*ThingVisualMixin
}
type ThingTactileView struct {
*ThingBaseMixin
*ThingTactileMixin
}
func main() {
obj := Thing {
ThingBaseMixin: ThingBaseMixin{"Bouncy Ball"},
ThingVisualMixin: ThingVisualMixin{"blue", true},
ThingTactileMixin: ThingTactileMixin{false},
Condition: "Good",
}
obj.visualView = &ThingVisualView{&obj.ThingBaseMixin, &obj.ThingVisualMixin}
obj.tactileView = &ThingTactileView{&obj.ThingBaseMixin, &obj.ThingTactileMixin}
b, _ := json.Marshal(obj)
fmt.Println(string(b))
//{"Name":"Bouncy Ball","Color":"blue","IsRound":true,"IsSoft":false,"Condition":"Good"}
b, _ = json.Marshal(obj.ThingVisualMixin)
fmt.Println(string(b))
//{"Color":"blue","IsRound":true}
b, _ = json.Marshal(obj.visualView)
fmt.Println(string(b))
//{"Name":"Bouncy Ball","Color":"blue","IsRound":true}
b, _ = json.Marshal(obj.tactileView)
fmt.Println(string(b))
//{"Name":"Bouncy Ball","IsSoft":false}
}
Here I've added a view into the object, but if you like, you can create it just when calling Marshal:
json.Marshal(ThingVisualView{&obj.ThingBaseMixin, &obj.ThingVisualMixin})
Or even without a preliminary type declaration:
json.Marshal(struct{*ThingBaseMixin;*ThingVisualMixin}{&obj.ThingBaseMixin,&obj.ThingVisualMixin})
Not sure why this isn't the preferred method, maybe due to the age of the post, but as far as I know, this is the 'best practice' way to handle this, with 'omitempty' tags for those which don't have to exist in the JSON object.
type Community struct {
Name string `json:"name"`
Description string `json:"description"`
Sources *[]Source `json:"sources,omitempty"`
Popularity int `json:"popularity"`
FavoriteCount int `json:"favorite-count"`
Moderators *[]string `json:"moderators,omitempty"`
Children *[]Community `json:"children,omitempty"`
Tracks *[]Track `json:"tracks,omitempty"`
}