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

Trait conflict when implementing `IntoActiveModel<A>` outside of entity model definition

Open ZodiacWind opened this issue 3 years ago • 5 comments

I found the the discussion, however it still happens to me.

Since I use sea-orm-cli to generate the entity crate automatically, I cannot implment the IntoActiveModel inside the crate, which will be overriden.

I tried to use the macro DeriveIntoActiveModel, but it didn't work either.

Could anyone tell me what could I do please?

Discussed in https://github.com/SeaQL/sea-orm/discussions/658

Originally posted by fairingrey February 19, 2022

Description

Trying to implement IntoActiveModel<A> outside of my entity model definition gives the following error:

  --> src/actions.rs:45:1
   |
45 | impl IntoActiveModel<user_account::ActiveModel> for UpdateUser {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `entity`:
           - impl IntoActiveModel<entity::user_account::ActiveModel> for <entity::prelude::UserAccount as sea_orm::EntityTrait>::Model;

I can't use DeriveIntoActiveModel either since I'm unaware how to specify (via attribute or etc) the specific ActiveModelTrait type that my type converts into since I define it outside of my crate.

Steps to Reproduce

// this is in entity::user_account::Model
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "user_account")]
pub struct Model {
    #[sea_orm(primary_key, auto_increment = false)]
    pub id: Uuid,
    pub created_at: DateTimeWithTimeZone,
    pub updated_at: DateTimeWithTimeZone,
    #[sea_orm(column_type = "Text")]
    pub name: String,
    pub email: String,
    #[sea_orm(column_type = "Text")]
    pub password: String,
    pub verified: bool,
}

// this exists in a separate, main crate where I perform other logic
#[derive(Debug)]
pub(crate) struct UpdateUser {
    pub(crate) name: Option<String>,
    pub(crate) email: Option<String>
}

impl IntoActiveModel<user_account::ActiveModel> for UpdateUser {
    fn into_active_model(self) -> user_account::ActiveModel {
        user_account::ActiveModel {
            name: sea_orm::IntoActiveValue::<_>::into_active_value(self.name).into(),
            email: sea_orm::IntoActiveValue::<_>::into_active_value(self.email).into(),
            ..::std::default::Default::default()
        }
    }
}

Expected Behavior

I expect it to be able to convert my type (defined outside of the entity crate) into an ActiveModel that I can use to update rows in my table.

Actual Behavior

Doesn't work as explained above.

Reproduces How Often

Always reproducible.

ZodiacWind avatar Sep 08 '22 15:09 ZodiacWind

I found that if I used the entity as an "extern" crate, the implementation wwon't work, while if I used the entity as a module, everything is OK.

ZodiacWind avatar Sep 08 '22 16:09 ZodiacWind

I found that if I used the entity as an "extern" crate, the implementation wwon't work, while if I used the entity as a module, everything is OK.

Hey @ZodiacWind, yes you're correct! The impl IntoActiveModel<...> for ... { } must be reside in the same crate with the entity.

billy1624 avatar Sep 13 '22 06:09 billy1624

I found that if I used the entity as an "extern" crate, the implementation wwon't work, while if I used the entity as a module, everything is OK.

Hey @ZodiacWind, yes you're correct! The impl IntoActiveModel<...> for ... { } must be reside in the same crate with the entity.

Thank you. In my option, it would be better if this restriction could be removed. According to the tutorial, the entity can be an somehow indepedent crate, while the IntoActiveModel is more coupled with my bussiness code.

In addtion, if I put the implementation with the entity crate together, especially in the same file, it will be overriden once the entity is regenerated.

What do you think? Is it possible or reasonable?

ZodiacWind avatar Sep 14 '22 04:09 ZodiacWind

I think it is more a limitation of Rust's orphan rule, so not likely to be changed soon.

But actually if you own the other struct in your crate, you can impl Into for it.

tyt2y3 avatar Sep 14 '22 09:09 tyt2y3

But actually if you own the other struct in your crate, you can impl Into for it.

Got it. That's how I make a workaround currently.

ZodiacWind avatar Sep 16 '22 09:09 ZodiacWind

Please let me know if you still have doubt about it

billy1624 avatar Oct 13 '22 10:10 billy1624