-
Notifications
You must be signed in to change notification settings - Fork 200
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
1601 default vals #1624
base: master
Are you sure you want to change the base?
1601 default vals #1624
Changes from all commits
dd3b533
515e7f7
3c00bd3
dbabf79
be2b59a
73d29bc
ec4d3d7
310166d
c0d4c48
b83259c
2aaa334
4fc4e34
bb549a6
cfa88f1
4e8a56e
aca9eb1
0c6dffd
83b319b
ce10af1
a93a0ab
e8380fe
5b2b577
44cdec3
8495d52
846ac8b
66996e2
16665ab
4360d6e
f3649df
fbfe5b3
7b4326e
7a7fec2
2e60d08
4a3a49f
7d9ebb8
caf2067
2f649ad
69c8647
fb3a655
f844402
23a5dc1
1b927d6
7cc745a
fbb6211
eadfe00
f59d3a0
8fd27de
c8bd906
eb64f2b
2f176a2
24829d4
72a7d4e
f0a4814
2f7bb68
63c578e
b1793cf
4a04c12
7f7ab12
12a0179
cc4f359
bfcb974
7b2ba87
26da4fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
{-| | ||
Module: IHP.IDE.Defaults.TableColumnDefaults | ||
Copyright: (c) digitally induced GmbH, 2020 | ||
-} | ||
module IHP.IDE.Defaults.TableColumnDefaults where | ||
|
||
import Test.Hspec | ||
import IHP.Prelude | ||
import qualified IHP.IDE.CodeGen.ControllerGenerator as ControllerGenerator | ||
import IHP.ViewPrelude (cs, plain) | ||
import qualified Text.Megaparsec as Megaparsec | ||
import IHP.IDE.CodeGen.Types | ||
import IHP.IDE.SchemaDesigner.Types | ||
import IHP.NameSupport | ||
import IHP.IDE.SchemaDesigner.Types | ||
|
||
|
||
{- | Takes a 'Text' value for the name and creates a default column where all values are empty lists, | ||
'Nothing' or 'False'; and for 'ColumnType', the default is 'PUUID'. | ||
|
||
Add a new field to the 'Column' type in the | ||
"IHP.IDE.SchemaDesigner.Types" file and then | ||
set its default value here | ||
|
||
Defined as: | ||
|
||
@ | ||
emptyColumn :: Column | ||
emptyColumn = Column { | ||
name = "" | ||
, columnType = PUUID | ||
, defaultValue = Nothing | ||
, notNull = False | ||
, isUnique = False | ||
, generator = Nothing | ||
} | ||
@ | ||
|
||
If you want a different 'PostgresType' you will need to | ||
specify with like so by either using a function: | ||
|
||
@setColumnType pgt = emptyColumn {columnType = pgt}@ | ||
|
||
Or | ||
|
||
Just as part of where you're calling it: | ||
|
||
@someDefaultColumnType = emptyColumn {columnType = PDate}@ | ||
-} | ||
emptyColumn :: Column | ||
emptyColumn = | ||
Column | ||
{ name = "" | ||
, columnType = PUUID | ||
, defaultValue = Nothing | ||
, notNull = False | ||
, isUnique = False | ||
, generator = Nothing | ||
} | ||
|
||
|
||
{- | Creates an empty table with all values empty. @unlogged@ is set to 'False'. | ||
|
||
Defined as such: | ||
|
||
@ | ||
emptyTable :: CreateTable | ||
emptyTable = CreateTable { | ||
name = "" | ||
, columns = [] | ||
, primaryKeyConstraint = PrimaryKeyConstraint [] | ||
, constraints = [] | ||
, unlogged = False | ||
} | ||
@ | ||
|
||
-} | ||
emptyTable :: CreateTable | ||
emptyTable = CreateTable | ||
{ name = "" | ||
, columns = [] | ||
, primaryKeyConstraint = PrimaryKeyConstraint [] | ||
, constraints = [] | ||
, unlogged = False | ||
} | ||
|
||
-- | Takes a name for our table and a list of column and inserts the list | ||
-- into to our empty table. | ||
defCreateTable :: Text -> [Column] -> CreateTable | ||
defCreateTable tablename columns = emptyTable { name = tablename | ||
, columns = columns } | ||
|
||
|
||
|
||
|
||
{- | Creates one default table with a singleton list of one 'setColumn'. | ||
|
||
Uses both `defCreateTable` and `setColumn`. | ||
|
||
@ | ||
defCreateTableWSetCol :: Text -- The name of the table | ||
-> Text -- The name of the column | ||
-> PostgresType -- The type of the column | ||
-> CreateTable -- The returned table | ||
@ | ||
|
||
-} | ||
defCreateTableWSetCol :: Text -> Text -> PostgresType -> CreateTable | ||
defCreateTableWSetCol tablename columnname pgt = defCreateTable tablename [setColumn columnname pgt] | ||
|
||
{- | Same as its progenitor `defCreateTableWSetCol` except it uses `setColumnN` | ||
-} | ||
defCreateTableWSetColN :: Text -> Text -> PostgresType -> CreateTable | ||
defCreateTableWSetColN tablename columnname pgt = defCreateTable tablename [setColumnN columnname pgt] | ||
|
||
|
||
{- | Takes the name of the table, the items you want inside the 'primaryKeyConstraint' and a list of columns | ||
to return a table where the primary key constraint is set. | ||
|
||
__Example:__ | ||
|
||
@ | ||
let orderTrucksTable = defCreateTablePKID "orderTrucks" ["order_id","truck_id"] cols | ||
where cols = map mkColumn ["order_id","truck_id"] | ||
mkColumn x = (setColumnN x PBigserial) | ||
@ | ||
|
||
>>> orderTrucksTable | ||
CreateTable { name = "orderTrucks" | ||
, columns = [ Column { name = "order_id", | ||
columnType = PBigserial, | ||
defaultValue = Nothing, | ||
notNull = True, | ||
isUnique = False, | ||
generator = Nothing} | ||
, Column { name = "truck_id", | ||
columnType = PBigserial, | ||
defaultValue = Nothing, | ||
notNull = True, | ||
isUnique = False, | ||
generator = Nothing} | ||
] | ||
, primaryKeyConstraint = PrimaryKeyConstraint {primaryKeyColumnNames = ["order_id","truck_id"]} | ||
, constraints = [] | ||
, unlogged = False} | ||
-} | ||
defCreateTablePKID :: Text -> [Text] -> [Column] -> CreateTable | ||
defCreateTablePKID name items cols = (defCreateTable name cols) {primaryKeyConstraint = PrimaryKeyConstraint items} | ||
|
||
|
||
{- | Allows you to set the name and columnType. Uses `emptyColumn` as its base | ||
|
||
If other values need to be changed, this can be done using: | ||
@(setColumn a b){..}@ | ||
|
||
__Example:__ | ||
|
||
>>> setColumn "user_id" PTrigger | ||
Column {name = "user_id", columnType = PTrigger, defaultValue = Nothing, notNull = False, isUnique = False, generator = Nothing} | ||
|
||
-} | ||
setColumn :: Text -> PostgresType -> Column | ||
setColumn name pgt = emptyColumn { name = name | ||
, columnType = pgt | ||
} | ||
|
||
-- | A version of `setColumn` where @notNull = True@ | ||
setColumnN :: Text -> PostgresType -> Column | ||
setColumnN n p = (setColumn n p) {notNull = True} | ||
|
||
-- | Sets a column to have a default value. Would recommend using in conjunction with `setColumn` | ||
setColumnDefaultVal :: Maybe Expression -> Column -> Column | ||
setColumnDefaultVal expression column = column {defaultValue = expression} | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Functions below this lines are IMO not a good idea. By having these very specific functions outside of the test suites we actually make tests harder to change, because you now need to look at two files to understands what's going on. So it would be better to undo the changes below and just make use of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So my thinking here was that if you had repeating units or tests, you can define them once, remember them and then use them as normal and so long as you know the definition of the table or column, you could:
Perhaps it's not useful for whole tables but certainly default values/columns that may repeat and have complicated structures. That said, I do see your point and there are several items that are superfluous; secondly, I'm sure if you needed to define repeatable units, you would define them as needed and perhaps on the test page like was done before. Therefore, I will revert the tests to defintions of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was also thinking that the writer would check the definition of the test by ctrl+clicking on the name and opening up the references window -> but I guess not everyone uses vscode for IDE which is understandable. |
||
{- | A recurring unit as found in many tests and files. | ||
|
||
Defined as such: | ||
|
||
>>> idColumn | ||
Column {name = "id", columnType = PUUID, defaultValue = Just (CallExpression "uuid_generate_v4" []), notNull = True, isUnique = False, generator = Nothing} | ||
|
||
-} | ||
idColumn :: Column | ||
idColumn = setColumnDefaultVal (Just (CallExpression "uuid_generate_v4" [])) $ setColumnN "id" PUUID | ||
|
||
{- | Give a column the text defined by 'text' and sets its 'columnType' to 'PText'. Uses `setColumnN`. | ||
|
||
__Example:__ | ||
|
||
>>> colText "example" | ||
Column {name = "example", columnType = PText, defaultValue = Nothing, notNull = True, isUnique = False, generator = Nothing} | ||
|
||
-} | ||
colText :: Text -> Column | ||
colText text = setColumnN text PText | ||
Comment on lines
+195
to
+196
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to also just write There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's written this way because By partially applying Once again, the option to write with |
||
|
||
|
||
{- | A recurring table that appears in many tests. | ||
|
||
This is its current definition: | ||
|
||
@ | ||
compilerSpecTable :: CreateTable | ||
compilerSpecTable = defCreateTablePKID "users" ["id"] cols | ||
|
||
where cols = [ idColumn | ||
, colText "firstname" | ||
, colText "lastname" | ||
, colText "password_hash" | ||
, colText "email" | ||
, setColumnN "company_id" PUUID | ||
, setColumn "picture_url" PText | ||
, setColumnDefaultVal (Just (CallExpression "NOW" [])) $ setColumnN "created_at" PTimestampWithTimezone | ||
] | ||
@ | ||
-} | ||
compilerSpecTable :: CreateTable | ||
compilerSpecTable = defCreateTablePKID "users" ["id"] cols | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As this is test related logic it shouldn't live here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe we can move this into some test module instead |
||
|
||
where cols = [ idColumn | ||
, colText "firstname" | ||
, colText "lastname" | ||
, colText "password_hash" | ||
, colText "email" | ||
, setColumnN "company_id" PUUID | ||
, setColumn "picture_url" PText | ||
, setColumnDefaultVal (Just (CallExpression "NOW" [])) $ setColumnN "created_at" PTimestampWithTimezone | ||
] | ||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function doesn't seem useful to me, why can't we just write
emptyTable { name = .. , columns = .. }
directly?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's more for speed: it means you don't have to write the record parts over and over again especially if they're the only two values in
emptyTable
being changed and you could quickly be certain that the only values changed were the name and the columns contained. If other values needed changing, then it's up to the writer to useemptyTable {..}
or(defCreateTable tablename columns){..})
-> both options are always available.Since they were a recurring feature, it made sense to write them this way initially.