1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! [`Lens`]: a model field's typed path paired with the reader of its value, built by [`lens!`].
use derive_where;
use Path;
/// A model field's typed path, which queries filter and sort on, paired with the function that
/// reads the field off a loaded record.
///
/// [`lens!`](crate::lens!) builds one from a single field name, so the two halves cannot name
/// different fields:
///
/// ```rust
/// # #[derive(Debug, Clone, toasty::Model, tablo_core::ModelColumns)]
/// # struct User { #[key] #[auto] id: uuid::Uuid, name: String }
/// # use tablo_core::{TextColumn, lens};
/// TextColumn::new(lens!(User.name)).searchable();
/// ```
///
/// The filters, the [`Field`](crate::Field) constructors and [`Tenancy`](crate::Tenancy) take a
/// `Lens` or a plain path; a column needs a `Lens`, since it renders the value it sorts on.
///
/// `P` is the type the path names, the field's own type except for a list: Toasty names a
/// `Vec<T>` field's path `List<T>`.
/// Build a [`Lens`] from a model and a field, or a chain of embedded fields.
///
/// `lens!(User.name)` is the path `User::fields().name()` paired with `|user| &user.name`. A
/// chain through a relation does not compile: a relation's records are not part of the row.
///
/// ```rust
/// # use tablo_core::{Lens, lens};
/// # #[derive(Debug, Clone, toasty::Model, tablo_core::ModelColumns)]
/// # struct User { #[key] #[auto] id: uuid::Uuid, name: String }
/// # #[derive(Debug, Clone, toasty::Embed)]
/// # struct Seo { title: String }
/// # mod blog {
/// # #[derive(Debug, Clone, toasty::Model, tablo_core::ModelColumns)]
/// # pub struct Post { #[key] #[auto] pub id: uuid::Uuid, pub title: String, pub seo: super::Seo }
/// # }
/// # use blog::Post;
/// # fn main() {
/// let name: Lens<User, String> = lens!(User.name);
/// let seo: Lens<Post, Seo> = lens!(Post.seo); // an embedded value, whole
/// let title: Lens<Post, String> = lens!(Post.seo.title); // an embedded struct's field
/// let qualified = lens!(crate::blog::Post.title);
/// # let _ = (name, seo, title, qualified);
/// # }
/// ```