Skip to content
New issue

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

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

Already on GitHub? # to your account

How to Specify Enum Literals? #76

Open
wbrickner opened this issue Mar 13, 2021 · 4 comments
Open

How to Specify Enum Literals? #76

wbrickner opened this issue Mar 13, 2021 · 4 comments
Labels
discussion disposition:close The tagged item can probably be closed question

Comments

@wbrickner
Copy link

Hello 👋🏻

I am trying to update a document.

I need to set the field standing, of type UserStanding:

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum UserStanding {
  /// the request is received, pending approval
  Pending,

  /// user account approved, active, fully enabled, etc.
  Active
}

#[derive(Model, Serialize, Deserialize, Clone, Debug)]
pub struct User {
  /// User standing (for customer # requests)
  pub standing: UserStanding
}

When I try to do this:

let update = {
    doc! {
      "$set": doc! {
        "location": &form.location,
        "standing": UserStanding::Active
      }
    }
  };

let result = User::find_one_and_update(
    &db, 
    doc! { "id": &path.user_id }, 
    update, None
  ).await;

I get the error

error[E0277]: the trait bound `Bson: From<UserStanding>` is not satisfied
  --> src/services/dashboard/users/review.rs:24:15
   |
24 |         "$set": doc! {
   |  _______________^
25 | |         "location": &form.location,
26 | |         "standing": UserStanding::Active
27 | |       }
   | |_______^ the trait `From<UserStanding>` is not implemented for `Bson`
   |
   = help: the following implementations were found:
             <Bson as From<&T>>
             <Bson as From<&[T]>>
             <Bson as From<&str>>
             <Bson as From<Vec<T>>>
           and 19 others
   = note: required by `std::convert::From::from`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

Thank you.

@thedodd
Copy link
Owner

thedodd commented Mar 15, 2021

Hey there. So, take a look at the bson docs here: https://docs.rs/bson/1.2.0/bson/ser/fn.to_bson.html

Though there are a few ways to deal with this, using this function to serialize your type as Bson is probably best, as it will ensure that if you actually have some BSON incompatible serde rules on your enum, this function will catch such issues (as an error).

That is generally what I would recommend in such cases, as this is the same mechanism which would be used if you have that enum type embedded in a struct which you are serializing/deserializing as bson.

@thedodd thedodd added discussion disposition:close The tagged item can probably be closed question labels Mar 15, 2021
@wbrickner
Copy link
Author

wbrickner commented Mar 16, 2021

So I would instead do something like

"$set": doc! {
  "standing": to_bson(&UserStanding::Active).unwrap()
}

Is that correct?

@wbrickner
Copy link
Author

wbrickner commented Mar 18, 2021

In another case, imagine I have

struct User {
  pub my_field: Option<MyWeirdType>
}

How can I find all documents which have a Some variant without explicitly constructing the thing I'm looking for?
Do I need to step down to the serde/BSON serialization level and explicitly search for something like:

{ "my_field": {"tag": "Some" } }

This feels ugly and error-prone, I hope there is a better way to do this.

@thedodd
Copy link
Owner

thedodd commented Mar 18, 2021

@wbrickner so, at the end of the day the enum is just another field in the DB. So as long as your enum field in indexed in the DB (otherwise it may be dead slow and may negatively impact your DB), then you have to treat it like any other field you are filtering on.

So if you know that your enum value serializes as {"tag": "Some"}, then you could manually write that, or you could use to_bson(...) to serialize its representation first and use that as the query. If you don't like those options, you could create your own as_bson method (or whatever you want to call it) which will just return the Bson enum representation for you as static/hard-coded values.

Thoughts?

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
discussion disposition:close The tagged item can probably be closed question
Projects
None yet
Development

No branches or pull requests

2 participants