file upload part map to model scala play2 - scala

file upload code
request.body.file("image").map { ing =>
val target = new java.io.File(s"./uploads/${ing.filename}")
ing.ref.moveTo(target, true)
}
How do you connect the ing.filename to the AboutImages "image" object so I can update the databases!
this is the nobel:
object AboutImages {
val images = {
get[Long]("about_us_images.id") ~
get[String]("about_us_images.image") ~
get[Option[Date]]("about_us_images.created_at") ~
get[Option[Date]]("about_us_images.updated_at") ~
get[Option[Int]]("about_us_images.position") ~
get[String]("about_us_images.name") map {
case id~image~created_at~updated_at~position~name => AboutImages (id, image, created_at, updated_at, position, name)
}
}
the is the form:
val details: Form[AboutImages] = Form(
mapping(
"id" -> longNumber,
"image" -> text,
"created_at" -> optional(date),
"updated_at" -> optional(date),
"position" -> optional(number),
"name" -> nonEmptyText
)(AboutImages.apply)
(AboutImages.unapply)
)

Not entirely sure I understand your question — are you having problems accessing the form components other than the file upload?
If so, take a look at the post Play file upload form with additional fields.

Related

Error inserting embedded documents into MongoDB using Scala

I use mongo-scala-driver 2.9.0 and this is a function saving a user's Recommendation List to MongoDB. The argument streamRecs is An Array of (productId:Int, score:Double). Now i want to insert a document consisting of an useId and its relevant reconmendation list recs. However, there is an error in the line val doc:Document = Document("userId" -> userId,"recs"->recs). Does anyone know what goes wrong?
def saveRecsToMongoDB(userId: Int, streamRecs: Array[(Int, Double)])(implicit mongoConfig: MongoConfig): Unit ={
val streamRecsCollection = ConnHelper.mongoClient.getDatabase(mongoConfig.db).getCollection(STREAM_RECS_COLLECTION)
streamRecsCollection.findOneAndDelete(equal("userId",userId))
val recs: Array[Document] = streamRecs.map(item=>Document("productId"->item._1,"score"->item._2))
val doc:Document = Document("userId" -> userId,"recs"->recs)
streamRecsCollection.insertOne(doc)
}
the document i want to insert into MongoDB is like this(it means an
user and his recommendation products and scores):
{
"_id":****,
"userId":****,
"recs":[
{
"productId":****,
"score":****
},
{
"productId":****,
"score":****
},
{
"productId":****,
"score":****
},
{
"productId":****,
"score":****
}
]
}
When creating a BSON document, declare the Bson type explicitly for each value in the key/value pair, like so:
/* Compose Bson document */
val document = Document(
"email" -> BsonString("email#domain.com"),
"token" -> BsonString("some_random_string"),
"created" -> BsonDateTime(org.joda.time.DateTime.now.toDate)
)
To see an example, please check https://code.linedrop.io/articles/Storing-Object-in-MongoDB.

How to add the new field to Object in Purescript

I am first about the Purescript.
I am going to add the new field to Object and send it as a function param.
But I can not find a good solution for this.
For example.
oldFiled = {
title : "title",
description : "d"
}
newField = {
time : "time"
}
//result after added new field
oldFiled = {
title : "title",
description : "d",
time : "time"
}
How can I do it?
If it's just about adding a single field you can use https://pursuit.purescript.org/packages/purescript-record/2.0.1/docs/Record#v:insert like so:
import Data.Record as Record
import Data.Symbol (SProxy(..))
oldFiled = {
title : "title",
description : "d"
}
newFiled = Record.insert (SProxy :: _ "time") "time" oldFiled
If you're merging records look at the merge union and disjointUnion functions in the Data.Record module

Checkbox lists in Play with Scala

I have ...
a Seq[RoleId] defining all roles that a user can get granted
a Userwith a property roles: Seq[RoleId], where the roles are those that the user has got granted
a Play controller preparing a form and providing the user (including her roles) and the Seq of available RoleIds to the html page as part of the form's data (including the mapping)
a Twirl template showing a checkbox for each available role
What I'd like to achieve is a list of checkboxes where every checkbox who's value is part of the user's roles is checked. So the list should show which of the available roles are granted to the user, as shown in this very refined prototype:
Name: [Doe, John]
Roles: [ ] Admin
[x] Manager
[x] Service Desk
[ ] Jack of all trades
if the user's name is John Doe with the roles Manager and Service Desk.
That seems rather simple, but I can't find a way to achieve it without some hacks (like circumventing the form and moving the role date to the Twirl template as a regular parameter; writing a custom mapper in the form handling code etc.). Isn't there a way to do it in the Play way without all that boilerplate ?
I googled hard, but I couldn't find any example that seemed to do it right. And Play's form processing docs weren't helpful either.
Any ideas ?
Upon refining my question I came up with a solution that worked.
I use the following form, which uses the case classes below to hold its data. As you can see there's a nested mapping inside, representing a list of roles and their state with regard to the user's roles (true meaning that the user has the role, false otherwise):
def userForm(implicit messages: Messages): Form[UserFormData] = Form(
mapping(
"firstName" -> nonEmptyText(minLength = 2, maxLength = 30),
"lastName" -> nonEmptyText(minLength = 2, maxLength = 40),
"email" -> email,
"roleAssignments" -> seq(
mapping(
"roleIdStr" -> nonEmptyText,
"isAssigned" -> boolean
)(RoleAssignment.apply)(RoleAssignment.unapply)
)
)(UserFormData.apply)(UserFormData.unapply)
)
case class UserFormData(firstName: String, lastName: String, email: String, roleAssignments: Seq[RoleAssignment])
case class RoleAssignment(roleIdStr: String, isAssigned: Boolean)
The controller just populates the form with data from the db:
def user(id: Long) = Action.async { implicit request =>
managerService.retrieveByIdWithRoles(id, Some(request.identity), request.remoteAddress).map { case (user, roles) =>
Ok(views.html.admin.administration.show_user(
userForm.fill(UserFormData(user.firstName, user.lastName, user.email, roleAssignments(roles)))))
}
}
private def roleAssignments(roles: Seq[Role]) = {
val roleIds = roles.map(_.id)
Roles.all.map { case id =>
RoleAssignment(id.toString, roleIds.contains(id))
}
}
And in the view template I repeat over the roleAssignments and use the index provided by repeatWithIndexto access the seq's elements:
#repeatWithIndex(userForm("roleAssignments")) { (roleAssignment, index) =>
#b4.checkbox(userForm(s"roleAssignments[$index].isAssigned"), '_text -> userForm(s"roleAssignments[$index].roleIdStr").value, '_custom -> true, 'readonly -> true)
}
Thank you #cchantep for pushing me to try harder.
The Play library provides an inputCheckboxGroup which works the same way as the inputRadioGroup.
In your Play controller:
def userForm(implicit messages: Messages): Form[UserFormData] = Form(
mapping(
"firstName" -> nonEmptyText(minLength = 2, maxLength = 30),
"lastName" -> nonEmptyText(minLength = 2, maxLength = 40),
"email" -> email,
"roleAssignmentIds" -> seq(text)
)(UserFormData.apply)(UserFormData.unapply)
)
val roleAssignmentOptions : List[(String, String)] = List("1" -> "Admin", "2" -> "Manager", "3" -> "Service Desk", "4" -> "Jack of All Trades")
Then in your Play Template:
#helper.inputCheckboxGroup(form("roleAssignmentIds"), roleAssignmentOptions)
This will display a list of checkboxes. The IDs ("1".."4") will be sent back back to the server when the checkboxes are checked. (If you fill the form in advance, you need to fill it in with the IDs - "1".."4" - as well.)

Return a casbah type findOne in a method

I'm making a system using scala and I make a method that return a "findOne".
Follow my code
def findOneByField(field:String, value:String): Any = {
val search: DBObject = MongoDBObject(field -> value)
return User.coll.findOne(search).get
}
I put the return type like Any because I cannot make equals MongoDb findOne return type.
I want to make this
val o = MongoDBObject("email"->"myemail#gmail.com")
findOneByField("email","myemail#gmail.com") == coll.findOne(o)
Boolean True
But if I get the type of coll.findOne, I receive this type:
res10: Option[com.myapptest.models.User.coll.T] = Some({ "_id" : { "$oid" : "57828cfe3b931047e1bb5455"} , "email" : "myemail#gmail.com" , "name" : "My Name" , "id" : "34863249182"})
I have no idea how return the same findOne in the method.
Could you help me?
Thanks! xD

Unexpected Decoding of = in Controller

From the front-end, I'm performing a jQuery POST with the following data:
[{name: "Kevin", age: 100, favoriteOperator:"="}]
This POST hits /sample URL.
In my controller, I read in the POST's body using:
def submit = Action { implicit request =>
val maybeRequestAsFormUrlEncoded: Option[Map[String, Seq[String]]] =
request.body.asFormUrlEncoded
Printing out map shows:
Map([{"name" : "Kevin", "age" : 100, "favoriteOperator" :" -> List("}])
Why is my favoriteOperator showing up as " -> List(" rather than "="?
Quite sure asFormUrlEncoded expects input like:
queryString=abc,def
anotherQueryString=blabla
which then is transformed into your map as:
Map("queryString" -> List("abc", "def"), "anotherQueryString" -> List("blabla"))
(I'm actually not so sure if abc,def and blabla really are deserialized into a list, that idea just comes because you get a list in your sample). Anyways, important is that asFormUrlEncoded expects key-value pairs separated by a = sign, that's why your string is taken apart like that. See also http://en.wikipedia.org/wiki/Url_encoding.
You might want to look into Json deserializers in play, as your request has a Json format:
http://www.playframework.com/documentation/2.2.x/ScalaJson