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

Can't update models with is_unique Validator #44

Open
mcvmcv opened this issue Jan 14, 2022 · 2 comments
Open

Can't update models with is_unique Validator #44

mcvmcv opened this issue Jan 14, 2022 · 2 comments
Assignees

Comments

@mcvmcv
Copy link

mcvmcv commented Jan 14, 2022

Describe the bug
Consider this model:

@kwdef mutable struct Mymodel <: AbstractModel
    id::DbId = DbID()
    name::String = ""
    updatefield::String = ""

Validation.validator([m::Type{Mymodel}) = ModelValidator([
    ValdiationRule(:name, MymodelsValidator.is_unique),
])

Create and save one:

julia > m = Mymodel(name="foo", updatefield = "bar") |> save!

Then try to edit it:

julia > m.updatefield = "baz"
julia > save!(m)

The validator sees the already existing Mymodel with name "foo" in the database, and doesn't let you save the updated one.

Error stacktrace

julia> save!(m)
[ Info: 2022-01-14 13:39:54 SELECT "mymodels"."id" AS "mymodels_id", "mymodels"."name" AS "mymodels_name", "mymodels"."updatefield" AS "mymodels_updatefield" FROM "mymodel" WHERE "name" = 'foo' ORDER BY mymodels.id ASC
[ Info: 2022-01-14 13:39:54 SELECT "mymodel"."id" AS "mymodels_id", "mymodels"."name" AS "mymodels_name", "mymodels"."updatefield" AS "mymodels_updatefield" FROM "mymodels" WHERE "updatefield" = 'baz' ORDER BY mymodels.id ASC
ERROR: SearchLight.Exceptions.InvalidModelException{Mymodel}(Mymodel
| KEY          | VALUE |
|--------------|-------|
| updatefield::String  | baz   |
| id::DbId     | 16    |
| name::String | foo   |
, SearchLight.Validation.ValidationError[SearchLight.Validation.ValidationError(:name, :is_unique, "already exists")], "Model Mymodel is not valid: Name already exists")
Stacktrace:
 [1] _save!!(m::Mymodel; conflict_strategy::Symbol, skip_validation::Bool, skip_callbacks::Vector{Symbol})
   @ SearchLight ~/.julia/packages/SearchLight/B9d2o/src/SearchLight.jl:194
 [2] save!!(m::Mymodel; conflict_strategy::Symbol, skip_validation::Bool, skip_callbacks::Vector{Symbol})
   @ SearchLight ~/.julia/packages/SearchLight/B9d2o/src/SearchLight.jl:164
 [3] #save!#40
   @ ~/.julia/packages/SearchLight/B9d2o/src/SearchLight.jl:161 [inlined]
 [4] save!(m::Mymodel)
   @ SearchLight ~/.julia/packages/SearchLight/B9d2o/src/SearchLight.jl:161
 [5] top-level scope
   @ REPL[835]:1

If any error is thrown, please copy from the REPL and paste it here

To reproduce
As above

Expected behavior
SearchLight would recognise the object in the DB as the same as the one you are updating, and allow you to update it

Additional context
Please include the output of
julia> versioninfo()
and
pkg> st

julia> versioninfo()
Julia Version 1.6.2
Commit 1b93d53fc4 (2021-07-14 15:36 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i3-6100 CPU @ 3.70GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, skylake)
Environment:
  JULIA_REVISE = auto

and

(Myproject) pkg> st
     Project Myproject v0.1.0
      Status `~/projects/Myproject/Project.toml`
  [336ed68f] CSV v0.9.11
  [c43c736e] Genie v4.9.0
  [e115e502] GenieAuthentication v1.1.0
  [6d011eab] Inflector v1.0.1
  [e6f89c97] LoggingExtras v0.4.7
  [739be429] MbedTLS v1.0.3
  [0aa819cd] SQLite v1.3.0
  [340e8cb6] SearchLight v2.0.1
  [21a827c4] SearchLightSQLite v2.0.0
  [4acbeb90] Stipple v0.19.3
  [30ddb3f0] StippleCharts v0.16.0
  [a3c5d34a] StippleUI v0.14.3
  [ade2ca70] Dates
  [56ddb016] Logging
@essenciary
Copy link
Member

@mcvmcv Thanks for reporting this. I'm pretty sure that's how it's supposed to work. Let's see...

1/ the model validator is in the user/app space and it's designed to be modified by the user as needed.
2/ the app outputs a snippet/template as the starting point - which seems to be old and incompatible with the DbId logic - and we should update.
3/ in one of my recent apps I implemented this. Can you try it? If good, we can update the template so we use it:

function is_unique(field::Symbol, m::T, args::Vararg{Any})::ValidationResult where {T<:AbstractModel}
  samename = findone(typeof(m); NamedTuple(field => getfield(m, field))... )
  samename === nothing || samename.id == m.id ||
    return ValidationResult(invalid, :is_unique, "already exists")

  ValidationResult(valid)
end

@essenciary essenciary self-assigned this Jan 14, 2022
@mcvmcv
Copy link
Author

mcvmcv commented Jan 16, 2022

Ah, so I should have named the topic "Can't update models with default is_unique Validator"?

Your new version works like a charm, many thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants