-
Notifications
You must be signed in to change notification settings - Fork 8
Upgrading to RDF.ex 0.9
This release is all about cleaning up the API of the RDF data structures to be more streamlined and provide a foundation for upcoming extensions. This lead however to a couple breaking changes.
Although the possible ways to provide input data to the RDF data structure functions was extended, one way which was possible previously was removed. It is no longer possible to provide the elements of a triple as separate arguments. So, the following is no longer supported:
RDF.Graph.add(graph, EX.S, EX.p, EX.o)
But calls like this can be easily migrated by just wrapping the statement elements in a tuple:
RDF.Graph.add(graph, {EX.S, EX.p, EX.o})
This affects the new
, add
, put
, delete
and include?
functions of RDF.Description
, RDF.Graph
and RDF.Dataset
.
The way in which initial statements are passed to the new
constructor function of RDF.Description
has been changed. It's no longer possible to provide initial statements directly. This way of initializing a RDF.Description
could lead to unpredictable results as it was (and still is) possible to provide triples with different subjects from which the subject of the description had to be determined.
A subject must now always be provided and initial statements (in any of the new forms for input data for RDF.Description
s) must be provided via the :init
option. So, something like this
RDF.Description.new({EX.S, EX.p, EX.o})
must be replaced with something like this:
RDF.Description.new(EX.S, init: {EX.p, EX.o})
Or just use the description DSL:
EX.S |> EX.p(EX.O)
The semantics of RDF.Graph.put/3
and RDF.Dataset.put/3
to overwrite just the statements with the same subject AND predicate was essentially the semantics of RDF.Description.put/3
, just on a graph respective dataset level. But this is not in-line with the usual semantics of put
in Elixir and therefore surprising for most Elixir developers, which probably would expect that put
would overwrite the complete description on RDF graphs, which is exactly how RDF.Graph.put/3
and RDF.Dataset.put/3
now behave. Note, that although it could be argued that RDF.Dataset.put/3
would have to overwrite complete graphs consequently now, this semantics wasn't chosen for practical reasons.
But since the old behavior of overwriting just the statements with the same subject and predicate is still also useful on RDF.Graph
s and RDF.Dataset
s functions with this behavior were added on them under the name put_properties/3
. This makes the migration very easy. If your code still relies on the old behavior you just have replace all RDF.Graph.put/3
and RDF.Dataset.put/3
calls with RDF.Graph.put_properties/3
and RDF.Dataset.put_properties/3
calls.
However: This behavior change of just being more destructive might not break your code depending on your test coverage. So, please check every call of these functions carefully.
The value/2
functions on RDF.Description
, RDF.Graph
, RDF.Dataset
and RDF.Data
previously had an optional second argument for a custom mapping function. The second argument of these values/2
functions is now reserved for keyword options, which allows for usage of the new RDF.PropertyMap
s for the mapping of predicates. The previous variant with the custom mapping function was extracted into a dedicated map/2
for exactly this use case.
The format for BGP query pattern was changed to be in-line with the input formats of RDF statements for RDF data structure functions. In particular this means:
- multiple objects can no longer be written directly after another, but must be wrapped in a list instead
- multiple predicate-object pairs on the same subject are no longer written by grouping them with square brackets, but in list of tuple pairs or maps instead
So, a query like this:
RDF.Graph.query(graph, [
{:s?,
[EX.p2, :o?],
[EX.p3, 42, 3.14, true]
},
{:o?, EX.p, "foo", "bar"},
])
can be replaced like this:
RDF.Graph.query(graph, [
{:s?, [
{EX.p2, :o?},
{EX.p3, [42, 3.14, true]}
]},
{:o?, EX.p, ["foo", "bar"]},
])
Alternatively the new map-based form and the new RDF.PropertyMap
s can be used:
property_map = %{p1: EX.p1(), p2: EX.p2(), p3: EX.p3()}
RDF.Graph.query(graph, %{
s?: %{
p2: :o?,
p3: [42, 3.14, true]
},
o?: %{p: ["foo", "bar"]},
},
context: property_map
)
This was done to be in-line with the Node structs.
As already experienced in the 0.8 release with RDF.Literal
changes it should be clear by now, that accessing the struct fields directly is not recommended. For this reason this release adds also more field accessor functions.