Getting result from a database sequence in Slick 3.0.0 - slick-3.0

I am trying to get the result of a query which is executed as a part of a sequence of actions passed as a parameter to DBIO.sequence() method of Slick 3.0. Below is the code snippet for the same.
val query = for {
(tt, th) <- tmpTrades join TableQuery[TrdHeader] on (_.tradeNum === _.tradeNum)
} yield (tt.tradeNum, th.internalInd, th.tradeStatusInd, th.tradeDt, th.tradeInputDt, th.lastModifyDt)
val queryAction = query.result
val actions = Seq(tmpTrades.schema.create, tmpTrades ++= trades.toSeq: _*, queryAction, tmpTrades.schema.drop)
val resultFuture = db.run(DBIO.sequence(actions))
I want the result of DBIO.sequence(actions) as a tuple of six attributes corresponding to the yield clause of the query and assign it to resultFuture variable. How can I achieve the same?
Thanks.

You should use flatMap instead of DBIO.sequence:
val myAction = tmpTrades.schema.create.flatMap { _ =>
tmpTrades ++= trades.toSeq
}.flatMap { _ =>
queryAction
}.flatMap { queryResult =>
// Return the result at the end.
tmpTrades.schema.drop.map { _ => queryResult }
}
db.run(myAction.transactionally)
Or the same thing as a for-yield:
val myAction = for {
_ <- tmpTrades.schema.create
_ <- (tmpTrades ++= trades.toSeq)
queryResult <- queryAction
_ <- tmpTrades.schema.drop
} yield queryResult
db.run(myAction.transactionally)

Related

Scala Regex pattern matching issue when using |

This is my example code.
object Patterns {
val workingPattern = """^thisworks[\w]+""".r
val problemPattern = """^(fail|error|bs|meh)[\w]+""".r
}
object TestMaker {
var works = scala.collection.mutable.Set[String]()
var needsWork = scala.collection.mutable.Set[String]()
var junk = scala.collection.mutable.Set[String]()
def add(someInput: String) = someInput match {
case Patterns.workingPattern() => works.update(someInput, true)
case Patterns.problemPattern() => needsWork.update(someInput, true)
case _ => junk.update(someInput, true)
}
}
When I call TestMaker.add("thisworks1234"), the string "thisworks1234" gets inserted into TestMaker's works set. It works as expected.
When I call TestMaker.add("this_is_just_junk"), the string "this_is_just_junk" gets inserted into the junk set - also as expected.
Here's the problem. When I call TestMaker.add("fail1234"), that string will also be inserted into the junk set. It should however be inserted into the needsWork set.
Where's my mistake?
You should use a non-capturing group with the second regex:
val problemPattern = """^(?:fail|error|bs|meh)[\w]+""".r
^^^
This is required because you are not referencing the captured value in your case.
Note that you can still use capturing groups within your patterns to ignore them later while matching with _*:
case Patterns.workingPattern(_*) => works.update(someInput, true)
case Patterns.problemPattern(_*) => needsWork.update(someInput, true)
case _ => junk.update(someInput, true)
See the IDEONE demo:
object Main extends App {
TestMaker.add("this_is_just_junk")
TestMaker.add("fail1234")
println(TestMaker.needsWork) // => Set(fail1234)
println(TestMaker.junk) // => Set(this_is_just_junk)
}
object Patterns {
val workingPattern = """^thisworks[\w]+""".r
val problemPattern = """^(fail|error|bs|meh)[\w]+""".r
}
object TestMaker {
var works = scala.collection.mutable.Set[String]()
var needsWork = scala.collection.mutable.Set[String]()
var junk = scala.collection.mutable.Set[String]()
def add(someInput: String) = someInput match {
case Patterns.workingPattern(_*) => works.update(someInput, true)
case Patterns.problemPattern(_*) => needsWork.update(someInput, true)
case _ => junk.update(someInput, true)
}
}

scala list addall method

This is my java code,
public void test( List<Map> courses)
{
....
List<Map> data = (List<Map>) response.getBody();
courses.addAll(data);
pageNo = pagination(response.getHeaders());
if(pageNo!=null)
{
params.put("pageNo", pageNo);
pAccountCourses(params, courses);
}
}
How to convert it into scala List[AccountCourses] , so that i can add courseList into accountCourseslist
def test(courseList: java.util.ArrayList[AccountCourses]) {
......
//getting json data
var pageNo: String = null
val body = response.body
val json = parse(body)
var accountCourseslist = json.extract[java.util.ArrayList[AccountCourses]]
accountCourseslist.addAll(courseList)
if (pageNo != null) {
params.put("pageNo", pageNo);
test(accountCourseslist);
}
}
case class AccountCourses(id: Int) //case class
how to perform addAll operation of list in scala?
How to convert java.util.ArrayList[AccountCourses] to scala list?
use scala.collection.JavaConverters._ :
import scala.collection.JavaConverters._
val javaList = new java.util.ArrayList[Int]()
val scalaList = javaList.asScala
val scalaImmutableList = scalaList.toList // will return immutable copy
How to perform addAll operation of list in scala?
Use ++= if it is mutable collection or ++ on immutable list:
scalaList ++= List(1,2,3,4,5) // will also update javaList
val result = scalaImmutableList ++ List(1,2,3,4,5) // will return new copy

Get object of case class from regex match

i'm working on scraping data from a webpage with scala regex-es, but i encountered problem with parsing result to object of some case class-es.
In following snippet i managed to scrape all the data, but i have no clue how to parse 3 elements from an iterator. I thought about something like:
val a :: b :: c :: _ = result.group(0).iDontKnowWha
Any ideas what can i do?
import model.FuneralSchedule
import play.api.libs.json.Json
import scala.io.Source
var date = "2015-05-05"
val source = Source.fromURL("http://zck.krakow.pl/?pageId=16&date=" + date).mkString
val regex = "(?s)<table>.+?(Cmentarz.+?)<.+?</table>".r
var thing: List[FuneralSchedule] = List()
var jsonFeed: List[Funeral] = List()
val regMatcher = "("
case class Funeral(hour: String, who: String, age: String) {
override def toString: String = {
"Cos"
}
}
//implicit val format = Json.format[Funeral]
val out = regex.findAllIn(source).matchData foreach { table =>
thing ::= FuneralSchedule(table.group(1), clearStrings(table.group(0)))
"""<tr\s?>.+?</\s?tr>""".r.findAllIn(clearStrings(table.group(0))).matchData foreach { tr =>
//TODO: Naprawic bo szlak trafia wydajnosc
val temp = """<td\s?>.+?</\s?td>""".r.findAllIn(tr.group(0)).matchData.foreach {
elem => println(elem)
}
//println(Json.toJson(thingy))
}
println("Koniec tabeli")
}
thing
//Json.toJson(jsonFeed)
println(removeMarkers("<td > <td> Marian Debil </ td>"))
def removeMarkers(s: String) = {
s.replaceAll( """(</?\s?td\s?>)""", "")
}
def clearStrings(s: String) = {
val regex = "((class=\".+?\")|(id=\".+?\")|(style=\".+?\")|(\\n))"
s.replaceAll(regex, "")
}
One way of doing it would be converting it to a Stream and matching it using stream's operators like this:
val a #:: b #:: c #:: _ = """([a-z]){1}""".r.findAllIn("a b c").toStream
then a, b and c is what you're looking for

Calling arbitrary number of WS.url().get() in sequence

I have a List[String] of URLs that I want to load and process (parse, store to database) in sequence.
I found only fixed-length examples, like:
def readUrls = Action {
implicit request => {
implicit val context = scala.concurrent.ExecutionContext.Implicits.global
val url1 = "http://some-website.com"
val url2 = "http://other-website.com"
Async {
for {
result1 <- WS.url(url1).get()
result2 <- WS.url(url2).get()
} yield {
Ok(result1.body + result2.body)
}
}
}
But instead of url1 and url2, I need to process this puppy:
val urls = List("http://some-website.com", "http://other-website.com")
Thanks a bunch for any tips and advice!
If you want to chain Futures together arbitrarily in sequence, foldLeft ought to do the job:
urls.foldLeft(Future.successful[String]("")){ case (left, nextUrl) =>
left.flatMap{ aggregatedResult =>
WS.url(nextUrl).get().map( newResult =>
aggregatedResult + newResult.body
)
}
}
Since you're just combining the request bodies together, I gave the foldLeft an initial value of a Future empty String, which each step in the fold will then add on the next response body.
def executeUrls(urls: List[String]): Future[String] = {
urls.foldLeft(Future(""))((accumulator, url) => {
accumulator.flatMap(acc => {
WS.url(url).get().map(response => {
acc + response.body
})
}
})
}
This should be what you're looking for, note that it returns a new Future.
Edit: apparently LimbSoup was faster.

Scala - replaceAllIn

First off, I'm new to Scala.
I'm trying to make a template parser in Scala (similar to Smarty (PHP)). It needs to search through the document, replacing anything inside "{{ }}" tags, with anything provided in the HashMap.
I'm currently stuck here:
import scala.collection.mutable.HashMap
import scala.io.Source
class Template(filename: String, vars: HashMap[Symbol, Any]) {
def parse() = {
var contents = Source.fromFile(filename, "ASCII").mkString
var rule = """\{\{(.*)\}\}""".r
//for(rule(v) <- rule findAllIn contents) {
// yield v
//}
//rule.replaceAllIn(contents, )
}
}
var t = new Template("FILENAME", new HashMap[Symbol, Any])
println(t.parse)
The part's that I've commented are things that I've thought about doing.
Thanks
I've come a little further...
import scala.collection.mutable.HashMap
import scala.io.Source
import java.util.regex.Pattern
import java.util.regex.Matcher
class Template(filename: String, vars: HashMap[Symbol, Any]) {
def findAndReplace(m: Matcher)(callback: String => String):String = {
val sb = new StringBuffer
while (m.find) {
m.appendReplacement(sb, callback(m.group(1)))
}
m.appendTail(sb)
sb.toString
}
def parse() = {
var contents = Source.fromFile(filename, "ASCII").mkString
val m = Pattern.compile("""\{\{(.*)\}\}""").matcher(contents)
findAndReplace(m){ x => x }
}
}
var t = new Template("FILENAME.html", new HashMap[Symbol, Any])
println(t.parse)
At the moment it just currently adds whatever was inside of the tag, back into the document. I'm wondering if there is an easier way of doing a find-and-replace style regexp in Scala?
I'd do it like this (String as key instead of Symbol):
var s : String = input // line, whatever
val regexp = """pattern""".r
while(regexp findFirstIn s != None) {
s = regexp replaceFirstIn (s, vars(regexp.findFirstIn(s).get))
}
If you prefer not using var, go recursive instead of using while. And, of course, a stringbuilder would be more efficient. In that case, I might do the following:
val regexp = """^(.*?)(?:{{(pattern)}})?""".r
for(subs <- regexp findAllIn s)
subs match {
case regexp(prefix, var) => sb.append(prefix); if (var != null) sb.append("{{"+vars(var)+"}}")
case _ => error("Shouldn't happen")
}
That way you keep appending the non-changing part, followed by the next part to be replaced.
There is a flavor of replaceAllIn in util.matching.Regex that accepts a replacer callback. A short example:
import util.matching.Regex
def replaceVars(r: Regex)(getVar: String => String) = {
def replacement(m: Regex.Match) = {
import java.util.regex.Matcher
require(m.groupCount == 1)
Matcher.quoteReplacement( getVar(m group 1) )
}
(s: String) => r.replaceAllIn(s, replacement _)
}
This is how we would use it:
val r = """\{\{([^{}]+)\}\}""".r
val m = Map("FILENAME" -> "aaa.txt",
"ENCODING" -> "UTF-8")
val template = replaceVars(r)( m.withDefaultValue("UNKNOWN") )
println( template("""whatever input contains {{FILENAME}} and
unknown key {{NOVAL}} and {{FILENAME}} again,
and {{ENCODING}}""") )
Note Matcher.quoteReplacement escapes $ characters in the replacement string. Otherwise you may get java.lang.IllegalArgumentException: Illegal group reference, replaceAll and dollar signs. See the blog post on why this may happen.
Here is also interesting way how to do the same using functions compose:
val Regexp = """\{\{([^{}]+)\}\}""".r
val map = Map("VARIABLE1" -> "VALUE1", "VARIABLE2" -> "VALUE2", "VARIABLE3" -> "VALUE3")
val incomingData = "I'm {{VARIABLE1}}. I'm {{VARIABLE2}}. And I'm {{VARIABLE3}}. And also {{VARIABLE1}}"
def replace(incoming: String) = {
def replace(what: String, `with`: String)(where: String) = where.replace(what, `with`)
val composedReplace = Regexp.findAllMatchIn(incoming).map { m => replace(m.matched, map(m.group(1)))(_) }.reduceLeftOption((lf, rf) => lf compose rf).getOrElse(identity[String](_))
composedReplace(incomingData)
}
println(replace(incomingData))
//OUTPUT: I'm VALUE1. I'm VALUE2. And I'm VALUE3. And also VALUE1