volatiletech / sqlboiler

Generate a Go ORM tailored to your database schema.
BSD 3-Clause "New" or "Revised" License
6.73k stars 544 forks source link

sqlboiler structs #441

Closed mogaal closed 5 years ago

mogaal commented 5 years ago

Hello, sorry in case the question is not sqlboiler related but I am facing the issue using it. I have the following SQL tables

CREATE TABLE subscriptions (
    id SERIAL NOT NULL PRIMARY KEY,
    plan_id int NOT NULL REFERENCES plans(id),
    comments text
);

CREATE TABLE plans (
    id SERIAL NOT NULL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    description text,
);

Inside the code I can pull (Load("Plan")) from Plan table the information:

subscription, _ := models.Subscriptions(Where("ID=?", v),Load("Plan")).One(ctx, db)
plan := subscription.R.Plan

My real problem is marshalling (json.Marshal(subscription)):

{
    "id": 2,
    "plan_id": 1,
    "comments": "Test"
}

but what I really want is:

{
    "id": 2,
    "plan_id": {
      "id": 1,
      "name": "Monthly"
    },
    "comments": "Test"
}

Honestly I have tried too many things but not luck for the time being. I managed to do something similar creating a custom structure:

type SubscriptionAndPlan struct {
    Subscription *models.Subscription `json:"subscription"`
    Plan         *models.Plan         `json:"plan"`
}

but it isn't the same (not nested). I honestly don't know what to do. I though in using a custom bind() but still not very clear how to implement bind with nested structures.

Is it good practice/normal to end up creating a custom structure everytime I want something nested or different than the default ones?

Alejandro

mogaal commented 5 years ago

Ok. I spent the night reading about the best to do it and I guess it is to create my own structures. For instance

type APISubscription struct {
    ID        int       `json:"id"`
    PlanID    int       `json:"plan_id"`
    Plan      *APIPlan  `json:"plan"`
    Comments  string    `json:"comments,omitempty"`
}

type APIPlan struct {
    ID          int    `json:"id"`
    Name        string `json:"name"`
    Comments string `json:"comments,omitempty"`
}

And probably the best way to fill it up would be to create:

func (s APISubscription) ToSubscription() APISubscription {
    return APISubscription{
        ID:              s.ID,
        PlanID:          s.PlanID,
        Plan:            s.Plan,
        Comments:        s.Comments,

    }
}

If someone has a better idea to make all of this simplier I would really appreciate it.