We already learned about simple Fixes (or Fix Functions) but there are three additional concepts in Fix selector, conditionals and binds. These Fix concepts were introduced by Catmandu (see functions, selector, conditionals and binds). But be aware Metafacture Fix does not support all of the specific functions, selectors, conditionals and binds from Catmandu. Check the documentation for an full overview of the supported fix functions.
The following code snippet shows examples of eachs of these concepts:
# Simple fix function
add_field("hello", "world")
remove_field("my.deep.nested.junk")
copy_field("stats", "output.$append")
# Conditionals
if exists("error")
set_field("is_valid", "no")
log("error")
elsif exists("warning")
set_field("is_valid", "yes")
log("warning")
else
set_field("is_valid", "yes")
end
# Binds - Loops
do list(path: "foo", "var": "$i")
add_field("$i.bar", "baz")
end
# Selector
if exists("error")
reject()
end
We already got to know simple fixes aka Functions. They are used to add, change, remove or otherwise manipulate elements. Simple fixes were introduced in Lesson 3.
The other three concepts help when you intend to use more complex transformations:
Conditionals are used to control the processing of fix functions. The included fix functions are not process with every workflow but only under certain conditions.
Selectors can be used to filter the records you want.
Binds are wrappers for one or more fixes. They give extra control functionality for fixes such as loops. All binds have the same syntax:
do Bind(params,…)
fix(..)
fix(..)
end
Conditionals are a common concept in programming and scripting languages. They control processes, in our scenario: transformations, with regard to specific requirements.
e.g. we have records some of them are of type book:
---
name: "The 13 1/2 lives of Captain Bluebear"
medium: "Book"
author: "Walter Moers"
language: "eng"
---
name: "The 13 1/2 lives of Captain Bluebear"
medium: "eBook"
author: "Walter Moers"
language: "eng"
---
name: "Die 13½ Leben des Käpt’n Blaubär"
medium: "Book"
author: "Walter Moers"
language: "ger"
---
name: "The 13 1/2 lives of Captain Bluebear"
medium: "Audio Book"
author: "Walter Moers"
narrator: "Bronson Pinchot"
language: "eng"
---
name: "Käpt'n Blaubär - Der Film"
medium: "Movie"
author: "Walter Moers"
director: "Hayo Freitag"
language: "ger"
If we want to add an element e.g. type for every record. Then we simply use the fix function add_field("type","BibliographicResource")
But if you want to add more specific type depending on the type, then we use contitionals:
e.g.:
only add_field("type","BibliographicResource")
if the medium contains Book:
if all_contain("medium","Book")
add_field("type","BibliographicResource")
end
if all_equal("medium","Book")
add_field("type","BibliographicResource")
end
Conditionals usually have the same syntax pattern:
if conditional("Parameter1","Parameter2")
fix-functions
end
If you want to add transformations for all that do not meet the condition with unless
:
unless all_equal("medium","Book")
add_field("type","Other")
end
if all_equal("medium","Book")
add_field("type","BibliographicResource")
else
add_field("type","Other")
end
if all_equal("medium","Book")
add_field("type","BibliographicResource")
elsif all_contain("medium","Audio")
add_field("type","AudioResource")
elsif all_match("medium",".*Movie.*")
add_field("type","AudioVisualResource")
else
add_field("type","Other")
end
Metafacture supports lots of conditionals, find a list of all of them here.
Hint: Some conditionals have variations with all_
or any_
while they behave in the same way if you process them on simple string-elements. They also can be used with arrays/lists then the conditional has different out-come depending on the fact that all (all_
) or at least one (any_
) value of an array matches the requierement.
At the moment Metafacture Fix only supports one of Catmandus selectors: reject
. With reject
you can kick out records that you do not want to process:
if all_contain("medium","Book")
reject()
end
This Fix used with our example above kicks out all records containing the word Book.
Selectors work in combination with conditionals to define the conditions that you want to kick out.
For the supported selectors see: https://github.com/metafacture/metafacture-documentation/blob/master/Fix-function-and-Cookbook.md#selectors
As mentioned above Binds* are wrappers for one or more fixes. They give extra control functionality for fixes such as loops. All binds have the same syntax:
do Bind(params,…)
fix(..)
fix(..)
end
The most commonly used is do list
. It allows to iterate over each element of an array.
If we have a record:
---
colours:
- red
- yellow
- green
and you use the fix
set_array("result") # To create a new array named result
upcase("colours[].*")
append("colours[].*"," is a nice color")
copy_field("colours[].*","result.$append")
It results in:
---
colours:
- "RED is a nice color"
- "YELLOW is a nice color"
- "GREEN is a nice color"
result: "RED is a nice color"
result: "YELLOW is a nice color"
result: "GREEN is a nice color"
If you want to only change it, under a certain condition:
if any_equal("colours[]","green")
set_array("result[]") # To create a new array named result
upcase("colours[].*")
append("colours[].*"," is a nice color")
copy_field("colours[].*","result[].$append")
end
This still transforms the all elements of an array because the conditional tests all elements not each individually.
To only tranform and copy the value green
to an X you have to use the do list
-Bind:
do list(path:"colours[]","var":"$i")
if any_equal("$i","green")
set_array("result[]") # To create a new array named result
upcase("$i")
append("$i"," is a nice color")
copy_field("$i","result[].$append")
end
end
See this example here in the playground.
TO BE CONTINUED …
TODO: Add Excercises.
Next lesson: 06 Metafacture CLI