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

Added functions for exporting and importing model field values from Dict #306

Merged
merged 3 commits into from
Dec 11, 2024
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 67 additions & 1 deletion src/ModelStorage.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,70 @@
module ModelStorage
using JSON3
using Stipple
import Stipple: INTERNALFIELDS, AUTOFIELDS, Reactive

const DEFAULT_EXCLUDE = vcat(INTERNALFIELDS, AUTOFIELDS)

"""
model_values(model::M; fields::Vector{Symbol} = Symbol[], exclude::Vector{Symbol} = Symbol[], json::Bool = false) where M
Exports the values of reactive fields from a Stipple model. Returns either a Dict of field-value pairs or a JSON string
if json=true.
### Example
@app TestApp2 begin
@in i = 100
@out s = "Hello"
@private x = 4
end
model = @init TestApp2
exported_values = Stipple.ModelStorage.model_values(model)
"""
function model_values(model::M; fields::Vector{Symbol} = Symbol[], exclude::Vector{Symbol} = Symbol[], json::Bool = false) where M
field_list = isempty(fields) ? fieldnames(M) : fields
excluded_fields = vcat(DEFAULT_EXCLUDE, exclude)

field_dict = Dict(field => getfield(model, field)[] for field in field_list
if field excluded_fields && getfield(model, field) isa Stipple.Reactive)

json ? JSON3.write(field_dict) : field_dict
end

"""
load_model_values!(model::M, values::Dict{Symbol, Any}) where M
load_model_values!(model::M, values::String) where M
Loads values into the fields of a ReactiveModel. Accepts either a Dict of field-value pairs or a JSON string.
### Example
values_dict = Dict(:i => 20, :s => "world", :x => 5)
Stipple.ModelStorage.load_model_values!(model, values_dict)
"""
function load_model_values!(model::M, values::Dict{Symbol, Any}) where M
model_field_list = fieldnames(M)
excluded_fields = DEFAULT_EXCLUDE

for (field, value) in values
if field excluded_fields && field model_field_list
model_field = getfield(model, field)

if model_field isa Reactive
model_field[] = value
else
@warn "Field $field is not reactive, skipping."
end
end
end

return model
end

function load_model_values!(model::M, values::String) where M
load_model_values!(model, Dict(JSON3.read(values)))
end

module Sessions

@@ -61,4 +127,4 @@ end

end # module Sessions

end # module ModelStorage
end # module ModelStorage
3 changes: 1 addition & 2 deletions src/Stipple.jl
Original file line number Diff line number Diff line change
@@ -100,10 +100,9 @@ export setchannel, getchannel
isempty(methods(notify, Observables)) && (Base.notify(observable::AbstractObservable) = Observables.notify!(observable))

include("ParsingTools.jl")
use_model_storage() && include("ModelStorage.jl")
include("NamedTuples.jl")

include("stipple/reactivity.jl")
use_model_storage() && include("ModelStorage.jl")
include("stipple/json.jl")
include("stipple/undefined.jl")
include("stipple/assets.jl")
34 changes: 33 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -559,4 +559,36 @@ end
@test Stipple.Layout.THEMES[][end] == my_css
remove_css(my_css, byname = true)
@test findfirst(==(my_css), Stipple.Layout.THEMES[]) === nothing
end
end

@testset "Exporting and loading model field values" begin
@app TestApp2 begin
@in i = 100
@out s = "Hello"
@private x = 4
end

model = @init TestApp2

exported_values = Stipple.ModelStorage.model_values(model)
@test exported_values[:i] == 100
@test exported_values[:s] == "Hello"
@test exported_values[:x] == 4

values_json = JSON3.write(exported_values)
exported_values_json = Stipple.ModelStorage.model_values(model, json = true)
@test values_json == exported_values_json

values_dict = Dict(:i => 20, :s => "world", :x => 5)
Stipple.ModelStorage.load_model_values!(model, values_dict)
@test model.i[] == 20
@test model.s[] == "world"
@test model.x[] == 5

values_json = Dict(:i => 30, :s => "zero", :x => 50) |> JSON3.write |> string
Stipple.ModelStorage.load_model_values!(model, values_json)
@test model.i[] == 30
@test model.s[] == "zero"
@test model.x[] == 50

end