Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persisting data in a single write #4

Open
agaviria opened this issue Mar 30, 2016 · 3 comments
Open

Persisting data in a single write #4

agaviria opened this issue Mar 30, 2016 · 3 comments

Comments

@agaviria
Copy link

@albrow First let me thank you for providing this package. I also have a question in mind and perhaps its more or less related to the zoom package. Say I have a model like this:

// Person holds all private information for a given Employee, Contractor or Temp.
type Person struct {
    FirstName string
    LastName  string
    Birthdate string
    SSN       string
    Residence
    Credentials
    zoom.RandomId
}

// Residence holds the primary home of address of a Person.
type Residence struct {
    Address string
    City    string
    State   string
    ZipCode string
}

// Credentials refers to login information.
type Credentials struct {
    Email      string
    Passwd     string
    IsVerified bool
}

How can one persist data within a Create function using a single save method (single write)? I'm getting an error in the controller.

unknown models.Person field 'Address' in struct literal
unknown models.Person field 'City' in struct literal
unknown models.Person field 'State' in struct literal
unknown models.Person field 'ZipCode' in struct literal
unknown models.Person field 'Email' in struct literal
unknown models.Person field 'Passwd' in struct literal
@albrow
Copy link
Owner

albrow commented Mar 31, 2016

@agaviria I would need to see more of your code to be certain, but it looks like you just have a syntax error in your struct literal.

In Go, when you embed structs, you need to initialize them like this:

person := Person{
    FirstName: "Bob",
    LastName:  "Jones",
    Residence: Residence{
        Address: "123 Lucky Drive",
        City:    "Sunny Meadows",
        State:   "CA",
        ZipCode: "12345",
    },
    Credentials: Credentials{
        Email:      "bob.jones@example.com",
        Passwd:     "password123",
        IsVerified: false,
    },
}

You cannot initialize them like this:

person := Person{
    FirstName: "Bob",
    LastName:  "Jones",
    Address: "123 Lucky Drive",
    City:    "Sunny Meadows",
    State:   "CA",
    ZipCode: "12345",
    Email:      "bob.jones@example.com",
    Passwd:     "password123",
    IsVerified: false,
}

See this playground example. This doesn't have anything to do with Zoom and is just the way Go works.

Zoom handles embedded structs fine, so you should just be able to save a Person model like you would normally. It's worth noting, however, that you will not be able to run queries on the embedded struct fields. So for example, you would not be able to find a person by their email address because Email is part of an embedded struct. See albrow/zoom#25 for more information about this limitation.

Let me know if that makes sense and fixes your problem.

@agaviria
Copy link
Author

Ok, so the composite literal declaration in the controller (personnel) is still returning undefined for Residence and Credentials.

// Personnel struct is of models.Person.
type Personnel struct{}

// Create will validate and create an instance of a Person.
func (c Personnel) Create(res http.ResponseWriter, req *http.Request) {
    r := render.New(render.Options{})
    personnelData, err := forms.Parse(req)
    if err != nil {
        panic(err)
    }

    var (
        dateRegex = regexp.MustCompile(`^\d{1,2}/\d{1,2}/\d{4}$`)
        ssnRegex  = regexp.MustCompile(`^\d{3}-\d{2}-\d{4}$`)
        val       = personnelData.Validator()
    )

    // validations
    val.Require("FirstName")
    val.Require("LastName")
    val.Require("Birthdate")
    val.Match("Birthdate", dateRegex) // Only accepts: dd/mm/yyyy
    val.Require("SSN")
    val.Match("SSN", ssnRegex) // Only accepts U.S. SSN format: NNN-NN-NNNN
    val.Require("Address")
    val.Require("City")
    val.Require("State")
    val.Require("ZipCode")
    val.Require("Email")
    val.MinLength("Pwd", 6)
    val.TypeBool("IsVerified")

    if val.HasErrors() {
        r.JSON(res, 422, val.ErrorMap())
        return
    }

    // save to database
    personnel := &models.Person{
        FirstName: personnelData.Get("FirstName"),
        LastName:  personnelData.Get("LastName"),
        Birthdate: personnelData.Get("Birthdate"),
        SSN:       personnelData.Get("SSN"),
        Residence: Residence{
            Address: personnelData.Get("Address"),
            City:    personnelData.Get("City"),
            State:   personnelData.Get("State"),
            ZipCode: personnelData.Get("ZipCode"),
            Email:   personnelData.Get("Email"),
        },
        Credentials: Credentials{
            Email:      personnelData.Get("Email"),
            Passwd:     personnelData.Get("Pwd"),
            IsVerified: personnelData.Get("IsVerified"),
        },
    }

    if err := models.Personnel.Save(personnel); err != nil {
        panic(err)
    }

    // render response of personnel
    r.JSON(res, 200, personnel)
}

@albrow
Copy link
Owner

albrow commented Apr 3, 2016

@agaviria I would like to help but I need more information. Are you seeing an error message and if so does the message include a line number? Does the server give a response and if so what is the exact response? Would it be possible to share more of your code, maybe by publishing your branch on GitHub?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants