sea-orm: Trait conflict when implementing `IntoActiveModel` outside of entity model definition

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.

Versions

❯ cargo tree | grep sea-
│   ├── sea-orm v0.6.0
│   │   ├── sea-orm-macros v0.6.0 (proc-macro)
│   │   ├── sea-query v0.21.0
│   │   │   ├── sea-query-derive v0.2.0 (proc-macro)
│   │   ├── sea-strum v0.23.0
│   │   │   └── sea-strum_macros v0.23.0 (proc-macro)
├── sea-orm v0.6.0 (*)

Database is Postgres 13.5, OS is ArchLinux 5.16.9-zen1-1-zen

Additional Information

Might be related to #322, #323, #340.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 15 (11 by maintainers)

Most upvoted comments

Hey @koptan, you manage to solve the errors by moving the trait implementation inside the entity crate?

Hi @baoyachi, Yes when I moved the trait implementation into entity create I was able to solve this issue.

I think this is happening because we already have an implicit implementation for IntoActiveModel with Marco and when I am trying to define my own implementation it’s breaking the orphan rules I guess: https://github.com/Ixrec/rust-orphan-rules

Again, I am still new to rust so maybe my feedback is so wrong.

Oh,Seems to be at the wrong person. @koptan

Hey @fairingrey, welcome!

The UpdateUser struct should have two non-null fields since both of them are required in the original Model.

So, we have…

#[derive(Debug, DeriveIntoActiveModel)]
pub(crate) struct UpdateUser {
    pub(crate) name: String,
    pub(crate) email: String,
}

Thanks for the welcome 🙂

I know that works, but maybe more related to #322 – Is it not possible for UpdateUser to act as a sort of changeset? i.e. if name is None then the active value for it should be unchanged. I’m using this for a PUT endpoint, so some values should stay the same.

EDIT: Will also mention that moving UpdateUser did fix the first issue I had, so thank you koptan

@baoyachi sorry my bad, I will modify the mention.