question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Naming of models in the new @binding API

See original GitHub issue

@essenciary The new API is really cool stuff. Here’s my idea to make it more robust and performant (still not breaking 🤣 )

We introduce an abstract subtype of ReactiveModels. All model-specific definitions like js_watch would always be defined for the abstract type.

It could be along the following lines:


function Stipple.root(::M)::String where {M<:ReactiveModel}
  root(M)
end

# remove extra chars from the `gensym()` call and convert "." to ","
# if we define the real model name to be the abstract model name prefixed with `'#'`
# the `vm()` will be identical for real and abstract type
function Stipple.root(::Type{M})::String where {M<:ReactiveModel}
  replace(replace(string(M), "." => "_", r"var\"#*([^#]+).*\"" => s"\1"), r"[^0-9a-zA-Z_-]+" => "")
end

# ------------------------------------------------------------
abstract type HHModel <: ReactiveModel end

# all js definitions go with the abstract model type
js_watch(::HHModel) = "console.log('Hi')"

# the real model type is defined as subtype of the abstract type
@reactive! mutable struct var"#HHModel" <: HHModel
    a::R{Int} = 1
    b::R{Float64} = 2
end

model = init(var"#HHModel")

vm(HHModel)
# "HHModel"

vm(var"#HHModel")
# "HHModel"

vm(model)
# "HHModel"

js_watch(model)
# "console.log('Hi')"

@reactive! mutable struct var"#HHModel" <: HHModel
    a::R{Int} = 1
    b::R{Float64} = 2
end

# after redefinition we need to make sure deps and routes are replaced
# for this to work we need to modify `stipple_deps()` to register the route under Symbol(vm(m)) instead of Symbol(m)
delete!(Stipple.DEPS, filter(x -> x isa Type && x <: HHModel, keys(Stipple.DEPS)))
Genie.Router.delete!(Symbol(vm(HHModel)))

# So the `@binding` macro should do something like

@reactive! mutable struct var"#HHModel" <: HHModel
    a::R{Int} = 1
    b::R{Float64} = 2
    c::R{Float64} = 3
end

delete!(Stipple.DEPS, filter(x -> x isa Type && x <: HHModel, keys(Stipple.DEPS)))
Genie.Router.delete!(Symbol(vm(HHModel)))

# -----------------------  testing  --------------------------

Stipple.DEPS[:test] = () -> ["Just for testing that we don't delete too much..."]

route("/") do 
    page(model, "Hello")
end

up()

Genie.Router.routes()
Stipple.DEPS

Any js functions would be preserved without redefinition and inference. That should be much more performant. What do you think?

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:25 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
hhaenselcommented, Nov 17, 2022

Cool! so the @in @out etc still work as previous?

Yip! Even better, it’s also possible to just import Stipple and ReactiveTools and it will work as well.

Maybe @vars or something makes more sense? Sounds good for the ReactiveTools. I’d still favour @type for people who want to declare their own models.

Re the @type example that’s practically the @reactive declaration, minus a few words.

Exactly.

The benefit or using it is that users don’t chose the name of the type and the name of the model does not change when the fields change?

The benefits are

  • the model doesn’t change its name
  • all type-specific function declarations will keep their validity without redefining
  • old syntax is supported
  • new syntax brings
    • no type declarations needed if the type is well-defined by the initial value
    • reactive type declaration without surrounding R{}. This is nice for people that use import rather than using because the parse_expression will check this and prefix with Stipple.otherwise.
    • non_reactive types are declared in a very similar way and types are also automatically attached

But this still needs to be written …

BTW, I added a js push function to do model.push(field) which works for both, reactive and non-reactive types as long as they are PUBLIC

0reactions
hhaenselcommented, Nov 29, 2022

Solved by #151

Read more comments on GitHub >

github_iconTop Results From Across the Web

Model Binding in ASP.NET Core | Microsoft Learn
The model binding and validation systems' behavior is driven by ModelMetadata. You can customize ModelMetadata by adding a details provider to ...
Read more >
Customising model-binding conventions in ASP.NET Core
A pattern I use when building Web APIs is to create commands to represent an API operation and models to represent resources or...
Read more >
Understanding Model Binding in ASP.NET Web API
Ok so now, the model binder first checks if the URL is decorated as required – “Ummm… Yes!! It has an API followed...
Read more >
MVC model binding naming convention for child objects?
Can someone tell me what the proper naming convention is for default model binding so that I don't have to employ the above...
Read more >
command-line-api/model-binding.md at main - GitHub
System.CommandLine has the default convention of binding Option arguments to either properties or constructor parameters by name. The name matching uses the ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found