Question about accessing types which are like #(something): {value1: Nat; value2: Nat}

Hey everyone,

I am currently trying to create a small app that lets users do reviews that contain a rating. These reviews are about locations, places, hotels, etc. In general, Is about traveling and vacations. I want the user to choose when he is creating the review, what type of review he wants to do. For example, his review will be about accommodation, a restaurant, or a cruise. If he chooses one of these types he must rate different things for every of these three. for example. a review about accommodation must contain a rating about the location and the view.

I want to validate the rating of the location and the view, by checking if it is bigger than 0 and lower than 100 before I push it in a List, hashMap, or something else.

My code:

public type ReviewModel = {
    id: Nat;
    author: UserModel;
    description: Text;
    rating: Nat;
    referringUser: UserModel;
    createdOn: Int;
    updatedOn: Int;
    typeofReview: ServiceType;

public type ReviewRequest = {
    description: Text;
    rating: Nat;
    referringUser: UserId;
    chooseType: ServiceType;

public type ServiceType = {
    #accommodation: {location: Nat; view: Nat};
    #cruise: {location: Nat; view: Nat};
    #restaurant: {location: Nat; view: Nat};

I was thinking that the user can choose if he wants accommodation, cruise, or restaurant with this type that I named ServiceType (I saw something like that in the documentation).
First Question: Is this right?

Secondly, I don’t know how to access the values of accommodation, cruise, and restaurant to validate them before being pushed to a List or hashMap. For example, I want to get into the #accomodation or #cruise to validate what they have inside (location and view).
Second Question: How could I access this kind of type?

Finally, is it the right way to think or is there a better way with Motoko?

Thank you!

First Answer: that looks sensible, but I expect you might iterate on that design.

Second Answer:

The way to access the data in variants is by pattern matching using the switch construct.

  func valid(n : Nat) : Bool { n >= 0 and n <= 100};

  public func validate (s : ServiceType) : Bool {
    switch (s) {
      // use a variant pattern with nested record pattern binding fields by identifiers l and v
      case (#accommodation {location = l; view = v}) { 
        valid(l) and valid(v)
      // use a variant pattern with nested record pattern binding fields by name Location and view
      case (#cruise {location; view}) {  
        valid(location) and valid(view)
      case (#restaurant r) { // use a variant pattern to bind r
        valid(r.location) and valid(r.view); // access fields via r

More explanation hopefully here Pattern matching :: Internet Computer


(The different cases illustrate three different ways of accessing the content of a variant value using pattern matching. Just pick whichever you prefer, of course.)

1 Like

Thank you very much for your answer it was really helpful! :slight_smile: