1use super::*;
2
3#[derive(Clone, Debug, Default, Eq, PartialEq)]
4pub struct RelationshipBuilder {
5 meta: Option<MetaOrAttrsBuilder>,
6 links: Option<LinksBuilder>,
7 data: Option<DataBuilder>,
8}
9
10impl Builder<'_> for RelationshipBuilder {
11 type Entity = Relationship;
12
13 fn finish(self) -> Result<Self::Entity, BuildErrors> {
14 Ok(Self::Entity {
15 meta: match self.meta {
16 None => None,
17 Some(meta) => Some(meta.finish()?),
18 },
19 links: match self.links {
20 None => None,
21 Some(links) => Some(links.finish()?),
22 },
23 data: match self.data {
24 None => None,
25 Some(data) => Some(data.finish()?),
26 },
27 })
28 }
29}
30
31impl RelationshipBuilder {
32 pub fn meta<M: Into<MetaOrAttrsBuilder>>(self, meta: M) -> Self {
33 Self {
34 meta: Some(meta.into()),
35 ..self
36 }
37 }
38
39 pub fn links<L: Into<LinksBuilder>>(self, links: L) -> Self {
40 Self {
41 links: Some(links.into()),
42 ..self
43 }
44 }
45
46 pub fn data<D: Into<DataBuilder>>(self, data: D) -> Self {
47 Self {
48 data: Some(data.into()),
49 ..self
50 }
51 }
52
53 pub fn meta1<N: ToString, V: Into<Value>>(self, name: N, meta1: V) -> Self {
54 let meta = self.meta.unwrap_or_default().item(name, meta1);
55
56 Self {
57 meta: Some(meta),
58 ..self
59 }
60 }
61
62 pub fn link<N: ToString, L: Into<LinkBuilder>>(
63 self,
64 name: N,
65 link: L,
66 ) -> Self {
67 let links = self.links.unwrap_or_default().link(name, link);
68
69 Self {
70 links: Some(links),
71 ..self
72 }
73 }
74}
75
76impl From<Relationship> for RelationshipBuilder {
77 fn from(relationship: Relationship) -> Self {
78 Self {
79 meta: relationship.meta.map(|meta| meta.into()),
80 links: relationship.links.map(|links| links.into()),
81 data: relationship.data.map(|data| data.into()),
82 }
83 }
84}
85
86impl<R: Into<ResourceBuilder>> From<R> for RelationshipBuilder {
87 fn from(resource: R) -> Self {
88 Self::default().data(resource.into())
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use crate::fixtures;
96
97 #[test]
98 fn empty() {
99 assert_eq!(
100 RelationshipBuilder::default().unwrap(),
101 Relationship {
102 meta: None,
103 links: None,
104 data: None,
105 },
106 );
107 }
108
109 #[test]
110 fn full() {
111 assert_eq!(
112 RelationshipBuilder::default()
113 .meta(
114 MetaOrAttrsBuilder::default()
115 .item("foo", 123)
116 .item("bar", "qwe"),
117 )
118 .links(
119 LinksBuilder::default()
120 .self_(LinkBuilder::new("http://self.com"))
121 .prev(
122 LinkBuilder::new("http://prev.com").meta(
123 MetaOrAttrsBuilder::default()
124 .item("foo", 123)
125 .item("bar", "qwe"),
126 ),
127 ),
128 )
129 .data(DataBuilder::Single(ResourceBuilder::new("qwerties")))
130 .unwrap(),
131 Relationship {
132 meta: Some(fixtures::meta_or_attrs()),
133 links: Some(Links {
134 other: HashMap::new(),
135 self_: Some(Link::String("http://self.com".into())),
136 related: None,
137 first: None,
138 last: None,
139 prev: Some(Link::Object(LinkObject {
140 href: "http://prev.com".into(),
141 meta: Some(fixtures::meta_or_attrs()),
142 })),
143 next: None,
144 about: None,
145 }),
146 data: Some(Data::Single(Resource {
147 type_: "qwerties".into(),
148 id: None,
149 meta: None,
150 links: None,
151 attributes: None,
152 relationships: None,
153 })),
154 },
155 );
156 }
157
158 #[test]
159 fn full_delegators() {
160 assert_eq!(
161 RelationshipBuilder::default()
162 .meta1("foo", 123)
163 .meta1("bar", "qwe")
164 .link("self", LinkBuilder::new("http://self.com"))
165 .link(
166 "prev",
167 LinkBuilder::new("http://prev.com").meta(
168 MetaOrAttrsBuilder::default()
169 .item("foo", 123)
170 .item("bar", "qwe"),
171 )
172 )
173 .data(DataBuilder::Single(ResourceBuilder::new("qwerties")))
174 .unwrap(),
175 Relationship {
176 meta: Some(fixtures::meta_or_attrs()),
177 links: Some(Links {
178 other: HashMap::new(),
179 self_: Some(Link::String("http://self.com".into())),
180 related: None,
181 first: None,
182 last: None,
183 prev: Some(Link::Object(LinkObject {
184 href: "http://prev.com".into(),
185 meta: Some(fixtures::meta_or_attrs()),
186 })),
187 next: None,
188 about: None,
189 }),
190 data: Some(Data::Single(Resource {
191 type_: "qwerties".into(),
192 id: None,
193 meta: None,
194 links: None,
195 attributes: None,
196 relationships: None,
197 })),
198 },
199 );
200 }
201
202 #[test]
203 fn with_data_from_resource() {
204 assert_eq!(
205 RelationshipBuilder::default()
206 .data(ResourceBuilder::new("qwerties"))
207 .unwrap(),
208 Relationship {
209 meta: None,
210 links: None,
211 data: Some(Data::Single(Resource {
212 type_: "qwerties".into(),
213 id: None,
214 meta: None,
215 links: None,
216 attributes: None,
217 relationships: None,
218 })),
219 },
220 );
221 }
222
223 #[test]
224 fn with_data_from_resources() {
225 assert_eq!(
226 RelationshipBuilder::default()
227 .data(vec![ResourceBuilder::new("qwerties")])
228 .unwrap(),
229 Relationship {
230 meta: None,
231 links: None,
232 data: Some(Data::Multiple(vec![Resource {
233 type_: "qwerties".into(),
234 id: None,
235 meta: None,
236 links: None,
237 attributes: None,
238 relationships: None,
239 }])),
240 },
241 );
242 }
243
244 #[test]
245 fn with_meta1_implicit() {
246 assert_eq!(
247 RelationshipBuilder::default()
248 .meta1("foo", 123)
249 .meta1("bar", "car")
250 .unwrap(),
251 Relationship {
252 meta: Some({
253 let mut meta = MetaOrAttrs::new();
254 meta.insert("foo".into(), Value::Number(123.into()));
255 meta.insert("bar".into(), Value::String("car".into()));
256 meta
257 }),
258 links: None,
259 data: None,
260 },
261 );
262 }
263
264 #[test]
265 fn with_link_implicit_from_str() {
266 assert_eq!(
267 RelationshipBuilder::default()
268 .link("self", "http://self.com")
269 .link("qwe", "http://qwe.com")
270 .unwrap(),
271 Relationship {
272 meta: None,
273 links: Some(fixtures::simple_links()),
274 data: None,
275 },
276 );
277 }
278
279 #[test]
280 fn implicit_from_entity() {
281 let relationship = Relationship {
282 meta: Some(fixtures::meta_or_attrs()),
283 links: Some(fixtures::simple_links()),
284 data: Some(Data::Single(Resource {
285 type_: "qwerties".into(),
286 id: Some("123".into()),
287 meta: None,
288 links: None,
289 attributes: None,
290 relationships: None,
291 })),
292 };
293
294 let builder: RelationshipBuilder = relationship.clone().into();
295
296 assert_eq!(builder.unwrap(), relationship);
297 }
298
299 #[test]
300 fn with_meta_implicit_from_entity() {
301 assert_eq!(
302 RelationshipBuilder::default()
303 .meta(fixtures::meta_or_attrs())
304 .unwrap(),
305 Relationship {
306 meta: Some(fixtures::meta_or_attrs()),
307 links: None,
308 data: None,
309 },
310 );
311 }
312
313 #[test]
314 fn with_links_implicit_from_entity() {
315 assert_eq!(
316 RelationshipBuilder::default()
317 .links(fixtures::simple_links())
318 .unwrap(),
319 Relationship {
320 meta: None,
321 links: Some(fixtures::simple_links()),
322 data: None,
323 },
324 );
325 }
326
327 #[test]
328 fn with_data_implicit_from_entity() {
329 assert_eq!(
330 RelationshipBuilder::default()
331 .data(Data::Single(Resource {
332 type_: "qwerties".into(),
333 id: Some("123".into()),
334 meta: None,
335 links: None,
336 attributes: None,
337 relationships: None,
338 }))
339 .unwrap(),
340 Relationship {
341 meta: None,
342 links: None,
343 data: Some(Data::Single(Resource {
344 type_: "qwerties".into(),
345 id: Some("123".into()),
346 meta: None,
347 links: None,
348 attributes: None,
349 relationships: None,
350 })),
351 },
352 );
353 }
354
355 #[test]
356 fn with_data_single_implicit_from_entity() {
357 assert_eq!(
358 RelationshipBuilder::default()
359 .data(Resource {
360 type_: "qwerties".into(),
361 id: Some("123".into()),
362 meta: None,
363 links: None,
364 attributes: None,
365 relationships: None,
366 })
367 .unwrap(),
368 Relationship {
369 meta: None,
370 links: None,
371 data: Some(Data::Single(Resource {
372 type_: "qwerties".into(),
373 id: Some("123".into()),
374 meta: None,
375 links: None,
376 attributes: None,
377 relationships: None,
378 })),
379 },
380 );
381 }
382}