bitwalker / strukt Goto Github PK
View Code? Open in Web Editor NEWExtends defstruct with schemas, changeset validation, and more
License: Apache License 2.0
Extends defstruct with schemas, changeset validation, and more
License: Apache License 2.0
When defining a field with a custom Ecto type or a parameterized type in Strukt, the generated typespec for the field defaults to any()
instead of the expected specific type (e.g., Ecto.UUID.t()). This issue may lead to less precise type checks and unexpected behaviors in development environments that rely on typespecs for static analysis or documentation purposes.
Example Code:
defmodule Foo do
use Strukt
defstruct do
field :bar, Ecto.UUID
end
end
Expected: The typespec for :bar
should be Ecto.UUID.t()
.
Actual: The typespec for :bar
is any()
.
The value_type
in the typespec.ex
function is not being correctly passed as a quoted expression. This results in the type not matching the expected case for processing.
Relevant code:
Line 56 in b2b8532
Line 141 in b2b8532
defines_type?
Check:The defines_type?
function check always fails. This function, intended to verify if the current module defines a given type, is not feasible in current Elixir compiler. The docs of defines_type?
say
Checks if the current module defines the given type (private, opaque or not).
This function is only available for modules being compiled.
Discussion related to this issue can be found here: Getting the @type module attribute
Relevant code:
Line 152 in b2b8532
We are using strukt
for validating external data input. For example we defined a schema with embeds_many
field: bar
:
defmodule Foo do
use Strukt
defstruct do
embeds_many :bar, Bar do
field :baz, :string
end
end
end
when using new/1
to parsing external data with wrong "embedded" type, it raise an unexpected error:
iex(2)> Foo.new(%{bar: "baz"})
** (Protocol.UndefinedError) protocol Enumerable not implemented for "baz" of type BitString. This protocol is implemented for the following type(s): Date.Range, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, Jason.OrderedObject, List, Map, MapSet, Range, Stream
(elixir 1.16.1) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.16.1) lib/enum.ex:166: Enumerable.reduce/3
(elixir 1.16.1) lib/enum.ex:4399: Enum.map_reduce/3
(elixir 1.16.1) lib/enum.ex:3865: Enum.with_index/2
(strukt 0.3.2) lib/params.ex:41: Strukt.Params.transform/4
(strukt 0.3.2) lib/params.ex:72: Strukt.Params.map_value_to_field/4
(elixir 1.16.1) lib/enum.ex:1700: Enum."-map/2-lists^map/1-1-"/2
iex:2: (file)
According to the stacktrace, it happens during conforming params:
Line 428 in b2b8532
returns a validation error:
{:error,
#Ecto.Changeset<
action: :insert,
changes: %{},
errors: [bar: {"is invalid", [validation: :embed, type: {:array, :map}]}],
data: #Foo<>,
valid?: false
>}
Hello, thanks for create an amazing library.
I met a dialyxir warning when I use this library:
# foo.ex
defmodule Foo do
use Strukt
defstruct do
field(:bar, :string)
field(:baz, :string)
end
end
and dialyxir(1.1.0) wanning at first line:
The pattern can never match the type.
Pattern:
_ = %Ecto.Changeset{:params => _}, [_ | _]
Type:
%Ecto.Changeset{
:action => :delete | :insert | nil | :update,
:changes => %{atom() => _},
:constraints => [map()],
:data => nil | map(),
:empty_values => _,
:errors => [{_, _}],
:filters => %{atom() => _},
:params => nil | %{binary() => _},
:prepare => [(_ -> any())],
:repo => atom(),
:repo_opts => [{_, _}],
:required => [atom()],
:types => nil | %{atom() => atom() | {_, _} | {_, _, _}},
:valid? => boolean(),
:validations => [{_, _}]
},
[]
I guess this message is due to when @cast_embed_fields
is []
we defined a "dead code" with type %Ecto.Changeset{:params => _}, [_ | _]
Lines 455 to 462 in 236c253
Currently strukt typing embeds_one :foo, Foo
's type as Foo.t()
, embeds_many :foos, Foo
as [Foo.t()]
:
Lines 72 to 77 in 2b6c643
it couldn't handle situations like
:foo
field could be null which type should be Foo.t() | nil
,:foos
could be nil, but element couldn't: [Foo.t()] | nil
:foos
could be nil, element's could be nil too: nil | [Foo.t() | nil]
any idea for handle these cases?
Given a struct below
defmodule CustomFieldsWithEmbeddedSchema do
use Strukt
defstruct do
field :name, :string
embeds_one :meta, Meta
end
end
defmodule Meta do
use Strukt
defstruct do
field(:name, :string)
end
end
in iex
iex(5)> CustomFieldsWithEmbeddedSchema.new(%{meta: nil})
** (FunctionClauseError) no function clause matching in CustomFieldsWithEmbeddedSchema.transform_params/4
The following arguments were given to CustomFieldsWithEmbeddedSchema.transform_params/4:
# 1
Meta
# 2
nil
# 3
nil
# 4
[]
lib/strukt.ex:1: CustomFieldsWithEmbeddedSchema.transform_params/4
lib/strukt.ex:564: CustomFieldsWithEmbeddedSchema.map_value_to_field/4
lib/strukt.ex:532: anonymous fn/5 in CustomFieldsWithEmbeddedSchema.transform_params/3
(elixir 1.12.2) lib/enum.ex:2385: Enum."-reduce/3-lists^foldl/2-0-"/3
lib/strukt.ex:529: CustomFieldsWithEmbeddedSchema.transform_params/3
lib/strukt.ex:356: CustomFieldsWithEmbeddedSchema.new/1
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.