Chapter: Node Field Attributes
Table of Contents
- Introduction
- Basic Annotations
- Granular Attributes
- Defining Attributes with Functions
- Field Definitions
- Links and Relationships
- Customizing Behavior with Inline Expressions
- Invalid Usages
- Summary and Conclusion
1. Introduction
Field attributes in Surreal orm allow developers to fine-tune the behavior and characteristics of each field within a database node. As you've already seen in the table of attributes, each attribute serves a specific purpose. In this chapter, we'll delve deeper into each attribute, providing examples and clarifying common misconceptions.
Attributes Table
Field Attributes
Attribute | Description | Type | Optional |
---|---|---|---|
rename | Renames the field. | string | Y |
link_one | Specifies a relationship to a singular record in another node table in the database. | model=NodeEdgeNode, connection ->edge->node | Y |
link_self | Specifies a relationship to a singular record in the same node table in the database. | Node | Y |
link_many | Specifies a relationship to multiple records in another node table in the database. | `Vec<S | |
relate | Generates the relation helpers for the Current Node struct to an edge and destination node. The corresponding field name is merely used as an alias in code generation and is read only and not serializable. e.g student:1->writes->book:2 | ||
type | Specify the valid surrealdb field's type. One of any, array, bool, datetime, decimal, duration, float, int, number, object, string, record. | surrealdb field type | Y |
assert | Assert the field's value meets a certain criteria using the an filter using value() function as an operation (e.g value().is_not(NONE) ) or in cond helper function for more complex filter assertion. e.g cond(value().is_not(NONE)).and(value().like("@codebreather")) . | inline code string | Y |
assert_fn | Provide a function to assert the field's value meets a certain criteria. This is similar to assert but is intended for an already created external function which is useful when reusing an assertion e.g is_email . | function name string | Y |
item_type | Only when for nested array. Specifies the type of the items of the array. | Option<FieldTypeWrapper> | Y |
item_assert | Only used for nested array. Asserts a condition on the content. | Option<syn::LitStr> | Y |
item_assert_fn | Only used for nested array. Specifies the function to assert a condition on the content. | Option<syn::Path> | Y |
define | Generates a DEFINE FIELD statement for the table. This overrides other specific definitions to prevent confusion and collision. You can also invoke an external function directly rather than inlining the function e.g define = "define_age()" | inline code string | Y |
define_fn | Generates a DEFINE FIELD statement for the table. This overrides other specific definitions to prevent confusion and collision. Same as define attribute but expects the function name instead rather than invocation i.e define_age instead of define_age() . You can also invoke an external function directly rather than inlining the function e.g `define = "def | ||
skip_serializing | When true, this field will be omitted when serializing the struct. | bool | Y |
2. Basic Annotations
Let's begin with a basic example. The Student
struct below uses minimal
annotations:
Here:
table
determines the name of the table in the database that corresponds to this struct.
3. Granular Attributes
For a more detailed configuration of a field, you can use granular attributes.
The Student
struct provides various usages:
Here:
type
specifies the data type of the field in the database.value
sets a default value for the field.assert
provides a condition that the field value must satisfy.permissions
specifies what operations can be performed on the field and under what conditions.
4. Defining Attributes with Functions
You can externalize the logic for defining attributes by using external functions. This aids in reusability and cleaner code:
Here:
define_fn
allows you to specify an external function that returns the definition of the table or field.
5. Field Definitions
Fields can be defined in multiple ways using surreal_orm
:
Inline Definitions:
External Function Invoked:
Using External Function Attributes:
Mixing and Matching:
6. Links and Relationships
You can define relationships between different structs (representing tables in
the database). Relationships can be one-to-one
, one-to-many
, or
many-to-many
.
For instance:
This indicates a one-to-one relationship between a student and a book.
7. Customizing Behavior with Inline Expressions
In surreal_orm
, you can use inline expressions to add custom behavior:
Here, the default value of age_teen_external_function_invoked_expr
is
determined by the get_age_by_group_default_value
function with
AgeGroup::Teen
as a parameter.
8. Invalid Usages
When using surreal_orm
, it's essential to be cautious about the attributes you
combine. Certain combinations are considered invalid and will result in
compilation errors.
1. Mixing value
and value_fn
:
These two attributes are mutually exclusive. You can't define a default value using both a direct expression and a function at the same time.
2. Mixing assert
and assert_fn
:
Similarly, you can't use both an inline assertion and an external function for the same purpose.
3. Mixing permissions
and permissions_fn
:
Permissions should be defined either inline or through an external function, but not both.
4. Combining define
and define_fn
:
These attributes are also mutually exclusive. When specifying a custom definition, you should use either an inline expression or an external function.
5. Using other attributes with define
or define_fn
:
When you use either the define
or define_fn
attribute, you cannot use any
other attributes (except for type
). This is because the definition provided
should be comprehensive and not require additional modifiers.
For example, the following combinations are invalid:
By being aware of these restrictions and avoiding the invalid combinations, you can ensure that your code remains consistent, clear, and free from compilation errors.
9. Summary and Conclusion
With surreal_orm
, you can easily map Rust structs to database tables,
customize field properties, define relationships, and more. This provides a
powerful way to interact with databases in a type-safe manner while keeping the
codebase clean and maintainable.
For a hands-on illustration, consider the following code snippet which provides a comprehensive overview of the various annotations:
This chapter is a starting point to dive deeper into surreal_orm
. With this
foundation, you can explore more advanced features and best practices to make
the most of this powerful ORM crate in Rust.