Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert from ActiveModel to Model #606

Closed
MattGson opened this issue Mar 14, 2022 · 8 comments · Fixed by #725 or #990
Closed

Convert from ActiveModel to Model #606

MattGson opened this issue Mar 14, 2022 · 8 comments · Fixed by #725 or #990
Assignees
Labels
good first issue Good for newcomers
Milestone

Comments

@MattGson
Copy link

MattGson commented Mar 14, 2022

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.

@Chaostheorie
Copy link
Contributor

Chaostheorie commented Mar 29, 2022

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}");
        });
}

@tyt2y3
Copy link
Member

tyt2y3 commented Mar 31, 2022

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 to T, which, thanks @Chaostheorie for the explanation. The trick is you should always know what type to expect in Rust.

@tyt2y3 tyt2y3 changed the title Convert from ActiveModel, ActiveValue<T> to Model, T Convert from ActiveModel to Model Mar 31, 2022
@tyt2y3 tyt2y3 added the good first issue Good for newcomers label Mar 31, 2022
@kirawi
Copy link
Contributor

kirawi commented May 12, 2022

What is the difference between ActiveModel and Model?

@billy1624
Copy link
Member

billy1624 commented May 12, 2022

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

@greenhandatsjtu
Copy link
Contributor

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.

@billy1624
Copy link
Member

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 { ... }

@greenhandatsjtu
Copy link
Contributor

@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!

@billy1624
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
Archived in project
6 participants