GenieFramework / GenieFramework/SearchLight.jl

Generating tables from struct definitions

Open
#74 1 comment 1 reaction 1 assignee Claimed by @PGimenez View on GitHub
enhancement
Dominant language
Julia
Stars
149
Forks
18
PR merge metrics
No merged PRs in 30d

Description

In ORMS like Django you only define a class for the data type and it'll automatically create the migration and the table with the `makemigration`and `migrate`commands. This certainly makes the workflow easier as the user only needs to modify one file. We could do something similar to avoid having to manually edit the migration file. I've taken a first step by creating the migration file from a struct

```julia
using Dates, SearchLight

function generate_migration(migration_name, struct_list...)
# Convert Julia types to DB column types
function type_to_dbcolumn(t)
return t == String ? :string :
t == Float64 ? :float :
t == Int ? :int : error("Unsupported type: $t")
end

# Generate migration for a single struct
function migration_for_struct(s, table_name)
field_names = fieldnames(s)
field_types = fieldtypes(s)

col_defs = [":$(field_names[i]) => :$(type_to_dbcolumn(field_types[i]))" for i in 2:length(field_names)]

return """
function up()
create_table(:$table_name) do
[
pk()
columns([
$(join(col_defs, ",\n\t\t"))
])
]
end
end

function down()
drop_table($table_name)
end
"""
end

# Process struct_list to separate structs from optional table names
structs_with_processed_names = []

@show struct_list
for item in struct_list
if typeof(item) == Tuple{DataType, String}
s, name = item
push!(structs_with_processed_names, (s, name))
elseif typeof(item) == DataType
s = item
push!(structs_with_processed_names, (s, lowercase(string(s))*"s"))
end
end
# Loop over each struct and generate the migration code
migrations = [migration_for_struct(s, table_name) for (s, table_name) in structs_with_processed_names]

# Bundle the generated migrations into a module
migration_code = """
module $migration_name

import SearchLight.Migrations: create_table, column, columns, pk, add_index, drop_table, add_indices

$(join(migrations, "\n\n"))

end
"""

# Save to file
filename = SearchLight.Migration.migration_file_name(migration_name)
open(filename, "w") do file
write(file, migration_code)
end
println("Migration saved to $filename")

return migration_code
end

```

Example usage

```julia
import SearchLight: AbstractModel, DbId
import Base: @kwdef
@kwdef mutable struct RandomVector <: AbstractModel
id::DbId = DbId()
x::String = ""
m::Float64 = 0.0
N::Int = 0
end

# Using the function with a mix of explicit table names and just structs
println(generate_migration("RandomVectors", RandomVector, (RandomVector, "my_table_name")))
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.