sea-orm
sea-orm copied to clipboard
Trait conflict when implementing `IntoActiveModel<A>` outside of entity model definition
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.
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.
I found that if I used the
entityas an "extern" crate, the implementation wwon't work, while if I used theentityas 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.
I found that if I used the
entityas an "extern" crate, the implementation wwon't work, while if I used theentityas 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?
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.
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.
Please let me know if you still have doubt about it