Skip to content

More context for ActiveModelBehaviour #962

@mohs8421

Description

@mohs8421

Motivation

When designing entities it is pretty common to write constraints into the datalayer. Sea-orm provides the ActiveModelBehaviour to allow users to fill in these pieces.
However, it is usually necessary to do some further analysis in these cases, like dropping some queries to check for further conditions to allow or deny a certain change. It might also be important to know the state of a record before the change that is going to be made, for example to implement a proper state transition, that might only be valid if some more data has been added to the record.

Proposed Solutions

It would be best if the ActiveModelBehaviour's signature would change to be like follows:

pub trait ActiveModelBehavior: ActiveModelTrait {
    /// Create a new ActiveModel with default values. Also used by `Default::default()`.
    fn new() -> Self {
        <Self as ActiveModelTrait>::default()
    }

    /// Will be called before saving
    // Note, that the former insert parameter is replaced by the option to the old_record, which fullfills the same purpose (and more), but is nevertheless a breaking change.
    fn before_save(self, old_record: Option<Model>, connection: &DatabaseConnection) -> Result<Self, DbErr> {
        Ok(self)
    }

    /// Will be called after saving
    fn after_save(
        model: <Self::Entity as EntityTrait>::Model,
        old_record: Option<Model>,
        connection: &DatabaseConnection,
    ) -> Result<<Self::Entity as EntityTrait>::Model, DbErr> {
        Ok(model)
    }

    /// Will be called before deleting
    fn before_delete(self, old_record: Option<Model>, connection: &DatabaseConnection) -> Result<Self, DbErr> {
        Ok(self)
    }

    /// Will be called after deleting
    fn after_delete(self, old_record: Option<Model>, connection: &DatabaseConnection) -> Result<Self, DbErr> {
        Ok(self)
    }
}

It might also be convenient to reduce the amount of parameters and pack them into a parameter-object struct like this:

pub struct SaveContext {
    old_record:connection:}

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions