Skip to content

Commit 7184107

Browse files
add Traversal.fetch_in_schema/2 and bang variation
1 parent 328cc73 commit 7184107

7 files changed

Lines changed: 45 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
44

55
## Unreleased
66

7+
## 0.0.10 [2026-06-17]
8+
- Rename `Traversal.get_in_schema/2` to `Traversal.fetch_in_schema!/2` and add safe `Traversal.fetch_in_schema/2`
9+
710
## 0.0.9 [2026-06-15]
811
- Fix regex intersection timeouts by replacing `greenery`/`pythonx` with rustler precompiled `regex_solver`
912

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Add to your list of dependencies
1414
```elixir
1515
def deps do
1616
[
17-
{:rock_solid, "~> 0.0.9", only: :test}
17+
{:rock_solid, "~> 0.0.10", only: :test}
1818
]
1919
end
2020
```

lib/rock_solid/context.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ defmodule RockSolid.Context do
9191
path = to_path(relative_pointer)
9292
reversed_path = Enum.reverse(path)
9393

94-
non_simplified = get_in_schema(base_schema, path)
94+
non_simplified = fetch_in_schema!(base_schema, path)
9595
simplified = Transformation.simplify(non_simplified, reversed_path)
9696
put_simplified(pointer, simplified)
9797
get_ref(pointer)

lib/rock_solid/migration.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ defmodule RockSolid.Migration do
457457
if property?(reversed_path) or definition?(reversed_path) do
458458
ref_behaviour(schema, reversed_path |> tl() |> Enum.reverse())
459459
else
460-
case get_in_schema(schema, path) do
460+
case fetch_in_schema!(schema, path) do
461461
%{"$schema" => value} -> ref_behaviour(Vocabulary.vocabulary(value))
462462
_ -> ref_behaviour(schema, remove_last(path))
463463
end

lib/rock_solid/traversal.ex

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -202,36 +202,59 @@ defmodule RockSolid.Traversal do
202202
end
203203
end
204204

205+
@doc """
206+
Same as `fetch_in_schema/2` but raises on error
207+
"""
208+
@spec fetch_in_schema!(any(), list(String.t())) :: any()
209+
def fetch_in_schema!(schema, path) do
210+
case fetch_in_schema(schema, path) do
211+
{:ok, value} -> value
212+
{:error, exc} when is_exception(exc) -> raise exc
213+
end
214+
end
215+
205216
@doc """
206217
Returns the value at the given location in the schema.
207218
208219
The path argument may contain a leading "#". You can convert a JSON Pointer string
209220
to a valid path by calling `to_path/1`
210221
211222
## Examples
212-
iex> RockSolid.Traversal.get_in_schema(%{"foo" => %{"bar" => "baz"}}, ["#", "foo", "bar"])
213-
"baz"
214223
215-
iex> RockSolid.Traversal.get_in_schema(%{"foo" => ["a", "b"]}, ["#", "foo", "1"])
216-
"b"
224+
iex> RockSolid.Traversal.fetch_in_schema(%{"foo" => %{"bar" => "baz"}}, ["#", "foo", "bar"])
225+
{:ok, "baz"}
226+
227+
iex> RockSolid.Traversal.fetch_in_schema(%{"foo" => ["a", "b"]}, ["#", "foo", "1"])
228+
{:ok, "b"}
229+
230+
iex> RockSolid.Traversal.fetch_in_schema(%{"foo" => ["a", "b"]}, ["#", "foo", "3"])
231+
{:error, %RockSolid.Traversal.InvalidPath{key: "3", schema: ["a", "b"]}}
232+
233+
iex> RockSolid.Traversal.fetch_in_schema(%{"foo" => 2}, ["#","bar"])
234+
{:error, %RockSolid.Traversal.InvalidPath{key: "bar", schema: %{"foo" => 2}}}
217235
"""
218-
@spec get_in_schema(any(), list(String.t())) :: any()
219-
def get_in_schema(schema, []), do: schema
220-
def get_in_schema(schema, ["#" | rest]), do: get_in_schema(schema, rest)
236+
@spec fetch_in_schema(any(), list(String.t())) :: {:ok, any()} | {:error, Exception.t()}
237+
def fetch_in_schema(schema, []), do: {:ok, schema}
238+
def fetch_in_schema(schema, ["#" | rest]), do: fetch_in_schema(schema, rest)
221239

222-
def get_in_schema(schema, [k | rest]) when is_map(schema) do
240+
def fetch_in_schema(schema, [k | rest]) when is_map(schema) do
223241
key = if Map.has_key?(schema, k), do: k, else: URI.decode(k)
224242

225243
if Map.has_key?(schema, key) do
226-
get_in_schema(schema[key], rest)
244+
fetch_in_schema(schema[key], rest)
227245
else
228-
# This one should never happen anyway
229-
raise InvalidPath, key: key, schema: schema
246+
{:error, %InvalidPath{key: key, schema: schema}}
230247
end
231248
end
232249

233-
def get_in_schema(schema, [k | rest]) when is_list(schema),
234-
do: get_in_schema(Enum.at(schema, String.to_integer(k)), rest)
250+
def fetch_in_schema(schema, [k | rest]) when is_list(schema) do
251+
with {index, ""} <- Integer.parse(k),
252+
{:ok, element} <- Enum.fetch(schema, index) do
253+
fetch_in_schema(element, rest)
254+
else
255+
_ -> {:error, %InvalidPath{key: k, schema: schema}}
256+
end
257+
end
235258

236259
@doc """
237260
Sets a value in the given (existing) path and returns the updated schema

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule RockSolid.MixProject do
22
use Mix.Project
33

44
@source_url "https://github.com/IgnacioGoldchluk/rock_solid"
5-
@version "0.0.9"
5+
@version "0.0.10"
66

77
def project do
88
[

test/rock_solid/traversal_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ defmodule RockSolid.TraversalTest do
66

77
doctest RockSolid.Traversal
88

9-
describe "get_in_schema/2" do
9+
describe "fetch_in_schema!/2" do
1010
test "raiss for invalid path" do
1111
schema = %{"properties" => %{"foo" => %{"type" => "string"}}}
1212
wrong_path = ["#", "properties", "bar"]
1313

1414
assert_raise Traversal.InvalidPath, ~r/Invalid key 'bar' .*/, fn ->
15-
Traversal.get_in_schema(schema, wrong_path)
15+
Traversal.fetch_in_schema!(schema, wrong_path)
1616
end
1717
end
1818
end

0 commit comments

Comments
 (0)