This project is an experimental work in progress and the interface may change.
We're using a Wordpress database which contains non normalised data in "meta" tables. These tables give us data as a set of keys and values that are attached to another object.
For example, a single post in wpposts may have multiple entries in wppostmeta such as location_lat
, location_lng
,
author
. We may wish to take those first two location_*
keys and put the values into a Location
struct, but leave
any other keys for use in different structs.
A handy way to do this is to turn the meta data into iterator, then use a filter_map. For example:
```rust struct Location { lat: String, lng: String, }
impl Location { fn guzzle(&mut self, (key, value): (String, String)) -> Option<(String, String)> { match key.asref() { "locationlat" => self.lat = value, "location_lng" => self.lng = value, _ => return Some(key, value); }; None } } ```
Used like this:
```rust let metadata = vec![ ("locationlat".tostring(), "51.5074° N".tostring()) ("locationlng".tostring(), "0.1278° W".tostring()) ("author".tostring(), "danielmason".tostring()) ];
let location = Location::default(); let leftovers = metadata.intoiter().filter_map(|data| location.guzzle(data)); ```
However, we don't want to have to implement the same function over and over. Instead we can use the custom derive
Guzzle
.
```rust
struct Location { #[guzzle(keys = ["locationlat"])] lat: String, #[guzzle(keys = ["locationlng"])] lng: String, }
let metadata = vec![ ("locationlat".tostring(), "51.5074° N".tostring()) ("locationlng".tostring(), "0.1278° W".tostring()) ("some-other-key".tostring(), "some-other-key".tostring()) ];
let remainingdata: Vec<(&str, String)> = testdata .intoiter() .filtermap(|v| location.guzzle(v)) .collect();
asserteq!(location.lng, "51.5074° N".tostring()); asserteq!(location.lat, "0.1278° W".tostring());
asserteq!(remainingdata, [("some-other-key", "some-other-key".to_string())]); ```