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

Add :any attribute type #13

Merged
merged 1 commit into from
Dec 17, 2024
Merged

Add :any attribute type #13

merged 1 commit into from
Dec 17, 2024

Conversation

abelino
Copy link
Collaborator

@abelino abelino commented Dec 13, 2024

Intended to be a passthrough attribute where the value is not validated or coerced but the value must be not nil at a minimum if optional: false. The any type is useful if you want to split out schemas where the top level schema is a generic envelope containing a nested data structure that could possibly be of a polymorphic nature. Example:

struct MQTT.AWS.Shadow.Update.V1

name "aws_shadow_update"

attribute :state do
  attribute :desired, :any
end
struct MQTT.Light.State.V1

name "light_state"

attribute [:schedule] do
  attribute :start, :datetime
  attribute :stop,  :datetime
end
with {:ok, shadow} <- Speck.validate(MQTT.AWS.Shadow.Update.V1, payload),
     {:ok, light_state} <- Speck.validate(MQTT.Light.State.V1, shadow.state.desired) do
  # do something with light_state
end

@abelino abelino requested a review from amclain December 13, 2024 04:29
@abelino abelino self-assigned this Dec 13, 2024
lib/speck.ex Outdated
@@ -103,6 +103,7 @@ defmodule Speck do
end
end

defp do_strict_validate(:any, value, _opts) when value != nil, do: value
Copy link
Member

@amclain amclain Dec 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does :any actually mean != nil, or is it more like Map.has_key? In other words, is the following :not_present, or should it be passed through?

params = %{
  "param1" => nil
}

Copy link
Collaborator Author

@abelino abelino Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave this some thought and this suggestion would change how other types/options behave. Lets observe how typed attributes currently behave:

When a field is optional, we currently check if the raw_value is nil and if it isn't nil, then a best attempt coercion occurs.
When a field is strict and not optional, we check the value type and by extension validate it's not nil.

So if we unwrap that into steps, we have:

  • type validation
  • optional validation

Now, with the :any type, that is essentially the absence of type so if we remove type validation, everything else should remain the same. However, you did uncover something, the guard clause for do_strict_validate(:any, value, _opts) is redundant because it is already handled prior to the validation sub-routines. So, I can get rid of that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Result of our offline convo:

Move forward with the same behavior as the other types. :any, optional: false considers a nil value to be :not_present, in other words "any non-nil value". To let everything pass through, use :any, optional: true.

README.md Outdated Show resolved Hide resolved
@abelino abelino merged commit 4bf9915 into main Dec 17, 2024
4 checks passed
@abelino abelino deleted the add-any-type branch December 17, 2024 04:25
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

Successfully merging this pull request may close these issues.

2 participants