-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: fetch parents/children with stops
Some stop functions were already using this relationship by effectively hand-rolling the relevant bits of the parsing. We can simplify by fully parsing the parent/child relationships in the main stop `Parser`, and having the special-purpose `Stop` functions delegate to a main `fetch` function as we do with other resources. Since we may be "starting from" either a parent or a child, we need a way to encode the complete data without recursing infinitely through this bidirectional link. For this purpose we introduce `:unloaded` as a special value indicating a relationship was not populated, similar to `Ecto.Association.NotLoaded`. This allows ending the recursion once we know we have all the data. It also allows the relationships to not be fetched in the first place, for functions that don't need this data or in contexts where stops are being parsed as a relationship on another resource.
- Loading branch information
1 parent
4aabf12
commit 1e87dca
Showing
8 changed files
with
254 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,70 @@ | ||
defmodule Screens.Stops.Parser do | ||
@moduledoc false | ||
|
||
def parse_stop(%{ | ||
"id" => id, | ||
"attributes" => %{ | ||
"name" => name, | ||
"location_type" => location_type, | ||
"platform_code" => platform_code, | ||
"platform_name" => platform_name | ||
} | ||
}) do | ||
alias Screens.RouteType | ||
|
||
def parse(%{"data" => data} = response) do | ||
included = | ||
response | ||
|> Map.get("included", []) | ||
|> Map.new(fn %{"id" => id, "type" => type} = resource -> {{id, type}, resource} end) | ||
|
||
Enum.map(data, &parse_stop(&1, included)) | ||
end | ||
|
||
def parse_stop( | ||
%{ | ||
"id" => id, | ||
"attributes" => %{ | ||
"name" => name, | ||
"location_type" => location_type, | ||
"platform_code" => platform_code, | ||
"platform_name" => platform_name, | ||
"vehicle_type" => vehicle_type | ||
}, | ||
"relationships" => relationships | ||
}, | ||
included, | ||
load_parent_station? \\ true | ||
) do | ||
parent_station = | ||
case get_in(relationships, ~w[parent_station data id]) do | ||
nil -> | ||
nil | ||
|
||
id -> | ||
data = Map.get(included, {id, "stop"}) | ||
|
||
if is_nil(data) or not load_parent_station?, | ||
# Only non-parent-stations can have a parent station. | ||
do: if(location_type != 1, do: :unloaded, else: nil), | ||
else: parse_stop(data, included) | ||
end | ||
|
||
child_stops = | ||
case get_in(relationships, ~w[child_stops data]) do | ||
nil -> | ||
# Only parent stations can have child stops. | ||
if location_type == 1, do: :unloaded, else: [] | ||
|
||
stop_references -> | ||
Enum.map(stop_references, fn %{"id" => id} -> | ||
# Always leave the `parent_station` of stops in `child_stops` unloaded, else parsing | ||
# would recurse infinitely. This covers the complete "stop family" regardless of where | ||
# we start. ("parent -> children" or "child -> parent -> all children") | ||
included |> Map.fetch!({id, "stop"}) |> parse_stop(included, false) | ||
end) | ||
end | ||
|
||
%Screens.Stops.Stop{ | ||
id: id, | ||
name: name, | ||
location_type: location_type, | ||
parent_station: parent_station, | ||
child_stops: child_stops, | ||
platform_code: platform_code, | ||
platform_name: platform_name | ||
platform_name: platform_name, | ||
vehicle_type: if(is_nil(vehicle_type), do: nil, else: RouteType.from_id(vehicle_type)) | ||
} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.