rid::store

Explains the Rid store attribute.

Store

There is exactly one main model per application which is called the Store. It is annotated with #[rid::store]. The Store is the main entry point to the application's state.

A Store is a #[rid::model] with some special characteristics. You can think of a #[rid:store] as a superset of a #[rid::model].

#[rid::store]
#[rid::structs(Todo)]
#[rid::enums(Filter)]
pub struct Store {
    last_added_id: u32,
    todos: Vec<Todo>,
    filter: Filter,
}

The #[rid::store] struct type has to be called Store. This is a convention that enables certain rid features and makes it easier to use and configure.

Annotations about Non-Primitive Types

As you can see we include type information of Todo and Filter via rid::structs and rid::enums respectively. This is necessary because the rid::store attribute only has access to the annotated Store struct and thus no way to deduce this information.

However in order to generate correct wrappers to access the Model fields it needs this information.

👉 read more about structs and enums.

The same is true for when creating Models with the #[rid::model] attribute.

The rid:RidStore Trait

The Store has to implement the RidStore trait which looks as follows:

pub trait RidStore<TMsg> {
    fn create() -> Self;
    fn update(&mut self, req_id: u64, msg: TMsg);
}

The create method initializes the Store and is only called once.

The update method is called each time a message of type TMsg is received. Note how it is called with the req_id which needs to be included with the message reply via rid::post in order to associate the two.

Example rid:RidStore Trait Implementation

impl rid::RidStore<Msg> for Store {
     fn create() -> Self {
        let todos = vec![Todo { title: "Learn Rust".to_string() }]; 
        Self { todos }
    }
    
    fn update(&mut self, req_id: u64, msg: Msg) {
        match msg {
            Msg::AddTodo(title) => {
                self.todos.push(Todo { title });
                rid::post(Reply::AddedTodo(req_id));
            }
        }
    }
}

#[rid::message(Reply)]
pub enum Msg { AddTodo(String) }

#[rid::reply]
pub enum Reply { AddedTodo(u64) }

Here we reply to the Add message with the Added reply including the req_id.

This allows rid to wait for the message to be handled by waiting for a reply whose req_id matches that of the sent message. As a result user code can await a message being handled on the Dart side.

await Store.instance.msgAddTodo("Understand Messages and Replies");

👉 read more about message and reply