scalatemplatesplayframeworktwirl

Get a string from an object in the template


Imagine I have a case class like so:

   case class Team(_id: Option[BSONObjectID], name: String = "", city: String = "", country: String = "")

And am passing this into my template (in Play 2.5/Scala/reactiveMongo 0.11.14) like this:

   @(teams : Seq[models.Team])

   ...

      @for(team <- teams){
            <tr>
                <td>@team._id</td>
                <td>@team.name</td>
                <td>@team.city</td>
                <td>@team.country</td>
            </tr>
      }

   ...

I need to get @team._id (which is currently type Option[BSONObjectID]) to a string - so just the BSONObjectID characters as a string. I have been trying to declare reusable values as documented here but I can't seem to get it right. Ordinarily I would use flatMap but this isn't working as expected within the template. Thanks for any help!


Following on from this it now seems that I should use a method within the case case class as @marcospereira suggested. However I am a little stuck (unsurprisingly!) on the syntax in a regex expression. So I am trying to make a string like this - BSONObjectID("59654f33b17946eac2323b3e") be just 59654f33b17946eac2323b3e. This is what I have:

def idAsString = _id.flatMap(bson => """\".*?(")""".r.findFirstIn(bson.toString)).getOrElse("")

But this also returns the quotation marks, e.g. "59654f33b17946eac2323b3e". As mentioned I don't want those - thanks to anyone that can help with this as I can't quite get the syntax right.


Solution

  • OK so this is the total answer (at least for me).

    Getting @team._id (which is currently type Option[BSONObjectID]) to a string is done by adding a method which does this (as suggested by @marcospereira [upvote]) to the case class. But I was still having issues as to how to do this, e.g. using regex, .split, etc. This is what I believe is the simplest way:

       case class Team(_id: Option[BSONObjectID] = None, name: String = "", city: String = "", country: String = "") {
    
           def idAsString = _id.map(_.stringify).getOrElse("")
    
       }
    

    So now I can call this method within the template to convert the Option[BSONObjectID] to the string like this:

       @(teams : Seq[models.Team])
    
       ...
    
          @for(team <- teams){
                <tr>
                    <td>@team.idAsString</td>
                    <td>@team.name</td>
                    <td>@team.city</td>
                    <td>@team.country</td>
                </tr>
          }
    
       ...
    

    Always seems obvious afterwards!