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

Adding support for custom struct initialization in tests #234

Closed kljensen closed 6 years ago

kljensen commented 6 years ago

This is a feature request. I am happy to work on the feature, and I would appreciate guidance on how best to do so.

My schema has constraints that make the randomize.Struct function not suitable to generating valid example model instances. For example, here is a table from my schema

CREATE TABLE IF NOT EXISTS users (
    id SERIAL PRIMARY KEY,
    nickname VARCHAR(50) UNIQUE NOT NULL,
    CONSTRAINT valid_nickname CHECK (nickname ~ '^[\w]{3,20}-[\w]{3,20}$'),
);

I would like a way to define my own alternative to randomize.Struct on a per-model basis in the tests. It is unclear to me how best to do this. Right now, I'm replacing it using a shell script.

(Thanks for your helpful project!)

Clearly,

aarondl commented 6 years ago

So, I think the proper way to do this is to use some custom import definitions (this is in the v3 branch) + custom templates. I'm not actually sure how else you'd do support for this. What do you think?

kljensen commented 6 years ago

Thanks @aarondl. Is there documentation in the v3 branch on the use of custom imports?

It is not clear to me how best to support this. Is it possible with dependency injection to include user-defined initialization functions on a per table basis in the generated code and tests?

(Slightly off topic---I felt on a few occasions it would have been nice to pass in SQLBoiler configuration options on a per-table and per-column basis using comments in my schema definition. Just a thought.)

aarondl commented 6 years ago

There is no documentation on the custom imports. Just check out the Config struct that's loaded into the toml. One thing that kinda sucks is if you override imports at a certain level, there's no merging that happens you simply take them over.

Config struct that gets loaded into toml: https://github.com/volatiletech/sqlboiler/blob/v3/boilingcore/config.go#L26 The struct at the bottom that defines the entire structure of imports: https://github.com/volatiletech/sqlboiler/blob/v3/importers/imports.go#L15 The code that actually loads it piecemeal into the struct: https://github.com/volatiletech/sqlboiler/blob/v3/main.go#L208

Hopefully this helps.

It's an interest thought about the configuration, but remember that sqlboiler doesn't actually work with schemas as much as it reads databases directly, and I'd wager that most database engines (gotta think cross-database here) won't preserve comments in a way we can access them.

aarondl commented 6 years ago

The reason there's no documentation is because docs always end up being last despite best intentions. There will be some before v3 is done.

aarondl commented 6 years ago

Hi there @kljensen. So the solution that has arisen in v3 for this kind of thing is to implement a custom type that understands the constraints. You can search for columns based on almost any specifier https://github.com/volatiletech/sqlboiler/tree/v3#types and replace the sqlboiler-driver inferred type with your own Nickname type that understands the constraints when generating random values. It can generate a correct random value by implementing the new Randomizer interface.

This is the solution we've gravitated towards. If it's insufficient please let me know. I have one more card in my back pocket for this one if we absolutely must.

kljensen commented 6 years ago

Thanks Aaron - that sounds reasonable. (Though, I haven't touched the code using sqlboiler in a while.)

On Mon, Jun 4, 2018 at 12:03 PM Aaron L notifications@github.com wrote:

Hi there @kljensen https://github.com/kljensen. So the solution that has arisen in v3 for this kind of thing is to implement a custom type that understands the constraints. You can search for columns based on almost any specifier https://github.com/volatiletech/sqlboiler/tree/v3#types and replace the sqlboiler-driver inferred type with your own Nickname type that understands the constraints when generating random values. It can generate a correct random value by implementing the new Randomizer https://github.com/volatiletech/sqlboiler/blob/652f7f121fd7127a7692c357cb01d8362b6eef90/randomize/randomize.go#L16 interface.

This is the solution we've gravitated towards. If it's insufficient please let me know. I have one more card in my back pocket for this one if we absolutely must.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/volatiletech/sqlboiler/issues/234#issuecomment-394408799, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEdwkn59JNJDt5VNZohnsIzQwk4hb5Jks5t5Vo5gaJpZM4RJ5B4 .