sea-orm icon indicating copy to clipboard operation
sea-orm copied to clipboard

Convert from ActiveModel to Model

Open MattGson opened this issue 3 years ago • 8 comments
trafficstars

Summary

Right now it is impossible to convert from ActiveModel -> Model or from ActiveValue<T> -> T ?

Motivation

When using insert_many(..) the return type is useless. ( I assume this is to support MySQL which does not allow returning clause)

So I need to get the models back by making another round-trip to the database (not the end of the world) or converting the ActiveModel's.

However, from my Vec<ActiveModel>, I cannot find a way to go to Vec<Model> or even Vec<Uuid>.

This makes it very hard to get the result of a multi-insert.

MattGson avatar Mar 14 '22 09:03 MattGson

Just my 2cts but, assuming you know that 1. Value is set and 2. Value is of type Uuid, wouldn't it be possible to use Value.as_ref_uuid() for the values?

For example, (going to Vec<Uuid> would be possible by using collect instead of for_each):

use sea_orm::ActiveValue;
use uuid::Uuid;

pub fn test() {
    let test_uuids = vec![
        ActiveValue::set(Uuid::new_v4()),
        ActiveValue::set(Uuid::new_v4()),
        ActiveValue::set(Uuid::new_v4()),
        ActiveValue::set(Uuid::new_v4()),
        ActiveValue::set(Uuid::new_v4()),
    ];

    test_uuids
        .iter()                // Iter<ActiveValue<…>>
        .cloned()              // impl Iter<Item = ActiveValue<…>>
        // unpack uuids
        .map(|active_value| {  
            active_value       // ActiveValue<…>
                .into_value()  // Option<Value>
                .unwrap()      // Value
                .as_ref_uuid() // Option<&Uuid>
                .unwrap()      // &Uuid
                .clone()       // Uuid
        })                     // impl Iter<Item = Uuid>
        .for_each(|uuid| {
            // test if uuids are usable
            println!("Uuid: {uuid}");
        });
}

Chaostheorie avatar Mar 29 '22 15:03 Chaostheorie

I think there are two problems:

  1. convert from ActiveModel into Model, which is sadly lacking for now. but I think it's a "good first issue", because our derive macros already generated the code for Model into ActiveModel, so it should be a mirror of that. The catch is, if any of the ActiveModel fields are NotSet, the conversion should fail (return Err).

  2. convert from ActiveValue<T> to T, which, thanks @Chaostheorie for the explanation. The trick is you should always know what type to expect in Rust.

tyt2y3 avatar Mar 31 '22 14:03 tyt2y3

What is the difference between ActiveModel and Model?

kirawi avatar May 12 '22 01:05 kirawi

Hey @kirawi, Model is an readonly struct that was retrieved from db. While ActiveModel is a stateful Model that was used for insert / update a row in the db.

https://www.sea-ql.org/SeaORM/docs/basic-crud/insert#model--activemodel

billy1624 avatar May 12 '22 09:05 billy1624

Hi @billy1624 , I'm a new comer and would like to work on this 'good first issue'. I'd appreciate it if you could give me some instructions.

greenhandatsjtu avatar May 13 '22 03:05 greenhandatsjtu

Hey @greenhandatsjtu, thanks for reaching out!

I think we can starts small, and take on the first task...

  1. convert from ActiveModel into Model, which is sadly lacking for now. but I think it's a "good first issue", because our derive macros already generated the code for Model into ActiveModel, so it should be a mirror of that. The catch is, if any of the ActiveModel fields are NotSet, the conversion should fail (return Err).

We could introduce a new trait, TryIntoModel, for this conversion behaviour. Similar to the conversion from Model to ActiveModel.

pub trait TryIntoModel<M>
where
    A: ModelTrait,
{
    fn try_into_model(self) -> Result<M, DbErr>;
}

Then, we implement it inside derive macros of active model. Again, similar to what we did for converting Model into ActiveModel but in reverse.

impl std::convert::TryFrom<ActiveModel> for <Entity as EntityTrait>::Model { ... }

impl sea_orm::TryIntoModel<<Entity as EntityTrait>::Model> for ActiveModel { ... }

billy1624 avatar May 13 '22 06:05 billy1624

@billy1624 thanks for your advice, now I know where to start. I will try to work on the first task, but I'm not sure I can make it, sorry if I bother you again when I meet problems that I can't solve. Or should I make a draft PR if I've made some progess, so you can point out where's wrong or what to do next in that PR, not in this issue anymore? Thanks again for your patient guidance!

greenhandatsjtu avatar May 13 '22 08:05 greenhandatsjtu

Hey @greenhandatsjtu, it's perfectly okay to ping me :D Please open a draft PR if you got any progress, all community members are encourage to conduct code review.

billy1624 avatar May 13 '22 09:05 billy1624