What is wrong with this ActiveSlick query?
import io.strongtyped.active.slick.ActiveSlick
import io.strongtyped.active.slick.models.Identifiable
import scala.slick.driver._
import scala.slick.driver.JdbcProfile._
trait MappingActiveSlickIdentifiable {
this: ActiveSlick =>
import jdbcDriver.simple._
case class Foo(name: String, id: Option[Int] = None) extends Identifiable[Foo] {
override type Id = Int
override def withId(id: Id): Foo = copy(id = Some(id))
}
class FooTable(tag: Tag) extends EntityTable[Foo](tag, "FOOS") {
def name = column[String]("NAME")
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def * = (name, id.?) <> (Foo.tupled, Foo.unapply)
}
val Foos = new EntityTableQuery[Foo, FooTable](tag => new FooTable(tag))
}
object MappingActiveSlickIdentifiable {
class Components(override val jdbcDriver: JdbcDriver)
extends ActiveSlick
with MappingActiveSlickIdentifiable {
import jdbcDriver.simple._
val db = Database.forURL("jdbc:h2:mem:active-slick", driver = "org.h2.Driver")
def createSchema(implicit s:Session): Unit = {
Foos.ddl.create
}
}
object Components {
val instance = new Components(H2Driver)
}
import Components.instance._
def main(args:Array[String]) : Unit = {
db.withTransaction { implicit s =>
createSchema
(1 to 3) foreach { i =>
val foo = Foo(s"foo $i")
val fooWithId : Foo = Foos.save(foo)
Foos.update(fooWithId.copy(name = "?"))
println(s"Foo: $foo, foo with id: $fooWithId")
assert(fooWithId.id.isDefined, "Foo's ID should be defined")
}
val q = for {
f <- Foos if f.name === "?"
} yield f.name
}
}
}
The error:
[error] /Volumes/Home/s/hello/slick-active/hw.scala:57: value === is not a member of scala.slick.lifted.Column[String]
[error] f <- Foos if f.name === "?"
You should NOT import there
import scala.slick.driver._
import scala.slick.driver.JdbcProfile._
import from a particular driver instead, e.g.
import scala.slick.driver.H2Driver._
Related
I'm trying to use fixture-context objects with async testing in ScalaTest.
The naive approach of simply combining the two doesn't compile. For example:
import org.scalatest.AsyncWordSpec
import scala.collection.GenTraversableOnce
import scala.concurrent.{ExecutionContext, Future}
import scala.math.Numeric.IntIsIntegral
trait Adder[T] {
implicit def num: Numeric[T]
def add(number: T): Unit
def result: Future[T]
}
object Foo {
def doubleSum[T](adder: Adder[T], numbers: GenTraversableOnce[T])(implicit ec: ExecutionContext): Future[T] = {
numbers.foreach(adder.add)
val num = adder.num
import num._
adder.result.map(result => result + result)
}
}
class FooSpec extends AsyncWordSpec {
trait IntAdder {
val adder = new Adder[Int] {
override implicit val num = IntIsIntegral
private var sum = Future.successful(num.zero)
override def add(number: Int): Unit = sum = sum.map(_ + number)
override def result: Future[Int] = sum
}
}
"Testing" should {
"be productive" in new IntAdder {
Foo.doubleSum(adder, Seq(1, 2, 3)).map(sum => assert(sum == 12))
}
}
}
This fails to compile with:
Error:(37, 11) type mismatch;
found : FooSpec.this.IntAdder
required: scala.concurrent.Future[org.scalatest.compatible.Assertion]
new IntAdder {
This is a legitimate error but I'm wondering what ways there are of solving this in a ScalaTest style.
I want to keep the fixture-context object since that allows me to use the stackable trait pattern.
What about:
import org.scalatest.compatible.Assertion
class FooSpec extends AsyncWordSpec {
def withIntAdder(test: Adder[Int] => Future[Assertion]): Future[Assertion] = {
val adder = new Adder[Int] { ... }
test(adder)
}
"Testing" should {
"be productive" in withIntAdder { adder =>
Foo.doubleSum(adder, Seq(1, 2, 3)).map(sum => assert(sum == 12))
}
}
}
Or
class FooSpec extends AsyncWordSpec {
trait IntAdder {
val adder = new Adder[Int] {
override implicit val num = IntIsIntegral
private var sum = Future.successful(num.zero)
override def add(number: Int): Unit = sum = sum.map(_ + number)
override def result: Future[Int] = sum
}
}
trait SomeMoreFixture {
}
"Testing" should {
"be productive" in {
val fixture = new IntAdder with SomeMoreFixture
import fixture._
Foo.doubleSum(adder, Seq(1, 2, 3)).map(sum => assert(sum == 12))
}
}
}
The best solution I have come up with so far is to do something like:
class FooSpec extends AsyncWordSpec {
trait IntAdder {
... // Same as in the question
val assertion: Future[compatible.Assertion]
}
"Testing" should {
"be productive" in new IntAdder {
val assertion = Foo.doubleSum(adder, Seq(1, 2, 3)).map(sum => assert(sum == 12))
}.assertion
}
}
I was hoping to reduce it down slightly more into:
class FooSpec extends AsyncWordSpec {
trait IntAdder extends (() => Future[compatible.Assertion]) {
... // Same as in the question
val assertion: Future[compatible.Assertion]
override def apply(): Future[Assertion] = assertion
}
"Testing" should {
"be productive" in new IntAdder {
val assertion = Foo.doubleSum(adder, Seq(1, 2, 3)).map(sum => assert(sum == 12))
}()
}
}
However this also doesn't compile due to:
Error:(42, 10) ';' expected but '(' found.
}()
You could have a mix of the fixture-context objects and the loan-fixtures methods patterns.
Something like this:
class FooSpec extends AsyncWordSpec {
// Fixture-context object
trait IntAdder {
val adder = new Adder[Int] {
override implicit val num = IntIsIntegral
private var sum = Future.successful(num.zero)
override def add(number: Int): Unit = sum = sum.map(_ + number)
override def result: Future[Int] = sum
}
}
// Loan-fixture method
def withContext(testCode: IntAdder => Future[compatible.Assertion]): Future[compatible.Assertion] = {
val context = new IntAdder {}
testCode(context)
}
"Testing" should {
"be productive" in withContext { context =>
import context._
Foo.doubleSum(adder, Seq(1, 2, 3)).map(sum => assert(sum == 12))
}
}
}
I have a case class, mappings and the object defined like this
import slick.driver.PostgresDriver.api._
import scala.concurrent.Await
import scala.concurrent.duration.Duration
case class Coffee(name : String, supID: Int, price: Double, sales: Int, total: Int) {
def save(): Coffee = { Coffees.save(this) }
def delete() { Coffees.delete(this) }
}
class Coffees(tag: Tag) extends Table[Coffee](tag, "coffee") {
def name = column[String]("cof_name", O.PrimaryKey)
def supID = column[Int]("sup_id")
def price = column[Double]("price")
def sales = column[Int]("sales", O.Default(0))
def total = column[Int]("total", O.Default(0))
def * = (name, supID, price, sales, total) <> (Coffee.tupled, Coffee.unapply)
}
object Coffees extends TableQuery(new Coffees(_)) {
lazy val db = DatabaseAccess.databases("db.test")
def save(coffee: Coffee): Coffee = {
val saveQuery = (this returning this).insertOrUpdate(coffee)
Await.result(db.run(saveQuery), Duration.Inf) match {
case Some(x) => x
case None => coffee
}
}
def delete(coffee: Coffee) = {
Await.result(db.run(this.filter(_.name === coffee.name).delete), Duration.Inf)
}
}
Now I want to write queries from other classes like this :
import com.typesafe.config.ConfigFactory
import org.scalatest.{FeatureSpec, GivenWhenThen, Matchers}
class CoffeeSpec extends FeatureSpec with GivenWhenThen with Matchers {
feature("Accessing coffees in the database") {
scenario("Adding a new coffee") {
val config = ConfigFactory.load()
DatabaseAccess.loadConfiguration(config)
lazy val db = DatabaseAccess.databases("db.test")
val coffee = Coffee("nescafe", 1, 20, 20, 40).save()
val temp = Coffees.filter(_.name === "nescafe")
temp.length should be (1)
coffee.delete()
}
}
}
This line
val temp = Coffees.filter(_.name === "nescafe")
Throws an error like this:
What is the best way to write the filter queries on the Coffees object?
Using slick 2.0 I have queries like:
Query(Coffees).filter(_.name is "coffee").firstOption.getOrElse(None)
I want to be able to do the similar queries using the new setup for all the data mappings.
Why am I getting these errors and how should I be able to make similar queries in slick 3?
Your queries are fine, but your CoffeeSpec file is missing an import:
import slick.driver.PostgresDriver.api._
Compilation should pass then.
Inspired by travisbrown, I'm trying to use a macro to create some "smart constructors".
Given
package mypkg
sealed trait Hello[A]
case class Ohayo[A,B](a: (A,B)) extends Hello[A]
and
val smartConstructors = FreeMacros.liftConstructors[Hello]
The macro should find all the subclasses of Hello, look at their constructors, and extract a few elements to populate this tree for the "smart constructor":
q"""
def $methodName[..$typeParams](...$paramLists): $baseType =
$companionSymbol[..$typeArgs](...$argLists)
"""
I hoped to get:
val smartConstructors = new {
def ohayo[A, B](a: (A, B)): Hello[A] = Ohayo[A, B](a)
}
but instead get:
error: type mismatch;
found : (A(in class Ohayo), B(in class Ohayo))
required: ((some other)A(in class Ohayo), (some other)B(in class Ohayo))
val liftedConstructors = FreeMacros.liftConstructors[Hello]
At a glance, the tree looks ok to me:
scala> q" new { ..$wellTyped }"
res1: u.Tree =
{
final class $anon extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
def ohayo[A, B](a: (A, B)): net.arya.constructors.Hello[A] = Ohayo[A, B](a)
};
new $anon()
}
but I guess it invisibly isn't. If I naively try to freshen up the typeParams with info.typeParams.map(p => TypeName(p.name.toString)), I get "can't splice A as type parameter" when I do the quasiquoting.
Where am I going wrong? Thanks for taking a look.
-Arya
import scala.language.experimental.macros
import scala.reflect.api.Universe
import scala.reflect.macros.whitebox
class FreeMacros(val c: whitebox.Context) {
import c.universe._
import FreeMacros._
def liftedImpl[F[_]](implicit t: c.WeakTypeTag[F[_]]): Tree = {
val atc = t.tpe
val childSymbols: Set[ClassSymbol] = subCaseClassSymbols(c.universe)(atc.typeSymbol.asClass)
val wellTyped = childSymbols.map(ctorsForSymbol(c.universe)(atc)).unzip
q"new { ..${wellTyped} }"
}
}
object FreeMacros {
def liftConstructors[F[_]]: Any = macro FreeMacros.liftedImpl[F]
def smartName(name: String): String = (
name.toList match {
case h :: t => h.toLower :: t
case Nil => Nil
}
).mkString
def subCaseClassSymbols(u: Universe)(root: u.ClassSymbol): Set[u.ClassSymbol] = {
val subclasses = root.knownDirectSubclasses
val cast = subclasses.map(_.asInstanceOf[u.ClassSymbol])
val partitioned = mapped.partition(_.isCaseClass)
partitioned match {
case (caseClasses, regularClasses) => caseClasses ++ regularClasses.flatMap(r => subCaseClassSymbols(u)(r))
}
}
def ctorsForSymbol(u: Universe)(atc: u.Type)(caseClass: u.ClassSymbol): (u.DefDef, u.DefDef) = {
import u._
import internal._
// these didn't help
// def clearTypeSymbol(s: Symbol): TypeSymbol = internal.newTypeSymbol(NoSymbol, s.name.toTypeName, s.pos, if(s.isImplicit)Flag.IMPLICIT else NoFlags)
// def clearTypeSymbol2(s: Symbol): TypeSymbol = internal.newTypeSymbol(NoSymbol, s.name.toTypeName, NoPosition, if(s.isImplicit)Flag.IMPLICIT else NoFlags)
// def clearTypeDef(d: TypeDef): TypeDef = internal.typeDef(clearTypeSymbol(d.symbol))
val companionSymbol: Symbol = caseClass.companion
val info: Type = caseClass.info
val primaryCtor: Symbol = caseClass.primaryConstructor
val method = primaryCtor.asMethod
val typeParams = info.typeParams.map(internal.typeDef(_))
// val typeParams = info.typeParams.map(s => typeDef(newTypeSymbol(NoSymbol, s.name.toTypeName, NoPosition, NoFlags)))
// val typeParams = info.typeParams.map(s => internal.typeDef(clearTypeSymbol2(s)))
val typeArgs = info.typeParams.map(_.name)
val paramLists = method.paramLists.map(_.map(internal.valDef(_)))
val argLists = method.paramLists.map(_.map(_.asTerm.name))
val baseType = info.baseType(atc.typeSymbol)
val List(returnType) = baseType.typeArgs
val methodName = TermName(smartName(caseClass.name.toString))
val wellTyped =
q"""
def $methodName[..$typeParams](...$paramLists): $baseType =
$companionSymbol[..$typeArgs](...$argLists)
"""
wellTyped
}
}
P.S. I have been experimenting with toolbox.untypecheck / typecheck per this article but haven't found a working combination.
you need using
clas.typeArgs.map(_.toString).map(name => {
TypeDef(Modifiers(Flag.PARAM),TypeName(name), List(),TypeBoundsTree(EmptyTree, EmptyTree))
}
replace
info.typeParams.map(p => TypeName(p.name.toString))
it si my code
object GetSealedSubClass {
def ol3[T]: Any = macro GetSealedSubClassImpl.ol3[T]
}
class GetSealedSubClassImpl(val c: Context) {
import c.universe._
def showInfo(s: String) =
c.info(c.enclosingPosition, s.split("\n").mkString("\n |---macro info---\n |", "\n |", ""), true)
def ol3[T: c.WeakTypeTag]: c.universe.Tree = {
//get all sub class
val subClass = c.weakTypeOf[T]
.typeSymbol.asClass.knownDirectSubclasses
.map(e => e.asClass.toType)
//check type params must ia s sealed class
if (subClass.size < 1)
c.abort(c.enclosingPosition, s"${c.weakTypeOf[T]} is not a sealed class")
// get sub class constructor params
val subConstructorParams = subClass.map { e =>
//get constructor
e.members.filter(_.isConstructor)
//if the class has many Constructor then you need filter the main Constructor
.head.map(s => s.asMethod)
//get function param list
}.map(_.asMethod.paramLists.head)
.map(_.map(e => q"""${e.name.toTermName}:${e.info} """))
val outfunc = subClass zip subConstructorParams map {
case (clas, parm) =>
q"def smartConstructors[..${
clas.typeArgs.map(_.toString).map(name => {
TypeDef(Modifiers(Flag.PARAM), TypeName(name), List(), TypeBoundsTree(EmptyTree, EmptyTree))
})
}](..${parm})=${clas.typeSymbol.name.toTermName} (..${parm})"
}
val outClass =
q"""
object Term{
..${outfunc}
}
"""
showInfo(show(outClass))
q"""{
$outClass
Term
}
"""
}
}
using like this
sealed trait Hello[A]
case class Ohayo[A, B](a: (A, B)) extends Hello[A]
object GetSealed extends App {
val a = GetSealedSubClass.ol3[Hello[_]]
val b=a.asInstanceOf[ {def smartConstructors[A, B](a: (A, B)): Ohayo[A, B]}].smartConstructors(1, 2).a
println(b)
}
I am sure there is a more elegant way of writing the following macro which prints the name and value of a variable:
def mprintx(c: Context)(linecode: c.Expr[Any]): c.Expr[Unit] = {
import c.universe._
val namez = (c.enclosingImpl match {
case ClassDef(mods, name, tparams, impl) =>
c.universe.reify(c.literal(name.toString).splice)
case ModuleDef(mods, name, impl) =>
c.universe.reify(c.literal(name.toString).splice)
case _ => c.abort(c.enclosingPosition, "NoEnclosingClass")
}).toString match {
case r_name(n) => n
case _ => "Unknown?"
}
val msg = linecode.tree.productIterator.toList.last.toString.replaceAll("scala.*\\]", "").replaceAll(namez+"\\.this\\.", "").replaceAll("List", "")
reify(myPrintDln(c.Expr[String](Literal(Constant(msg))).splice+" ---> "+linecode.splice))
}
def myPrintIt(linecode: Any) = macro mprintx
called by the following program:
object Zabi2 extends App {
val l = "zab"
val kol = 345
var zub = List("2", 89)
val zubi = List(zub,l,kol)
printIt(l)
printIt(l, kol, (l, zub),zubi)
}
which prints:
l ---> zab
(l, kol, (l, zub), zubi) ---> (zab,345,(zab,List(2, 89)),List(List(2, 89), zab, 345))
Thanks in advance for your help.
Here is a macro to print expressions and their values:
package mymacro
import scala.annotation.compileTimeOnly
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
#compileTimeOnly("DebugPrint is available only during compile-time")
class DebugPrint(val c: whitebox.Context) {
import c.universe._
def impl(args: c.Expr[Any]*): c.Tree = {
val sep = ", "
val colon = "="
val trees = args.map(expr => expr.tree).toList
val ctxInfo = s"${c.internal.enclosingOwner.fullName}:${c.enclosingPosition.line}: "
val treeLits = trees.zipWithIndex.map {
case (tree, i) => Literal(Constant((if (i != 0) sep else ctxInfo) + tree + colon))
}
q"""
System.err.println(StringContext(..$treeLits, "").s(..$trees))
"""
}
}
#compileTimeOnly("DebugPrint is available only during compile-time")
object DebugPrint {
def apply(args: Any*): Any = macro DebugPrint.impl
}
Example:
package myapp
import mymacro.DebugPrint
case class Person(name: String, age: Int)
object Main extends App {
val x = 5
val y = "example"
val person = Person("Derp", 20)
DebugPrint(x, y, person, person.name, person.age)
def func() = {
val x = 5
val y = "example"
val person = Person("Derp", 20)
DebugPrint(x, y, person, person.name, person.age)
}
func()
}
Output:
myapp.Main.<local Main>:12: Main.this.x=5, Main.this.y=example, Main.this.person=Person(Derp,20), Main.this.person.name=Derp, Main.this.person.age=20
myapp.Main.func:18: x=5, y=example, person=Person(Derp,20), person.name=Derp, person.age=20
Works well with scala 2.12.12.
I want to be able to do something like this:
prepare form:
val formDescription = formBuilder(_.textField[User](_.firstName)
.textField[User](_.lastName)
).build
showForm(formDescription)
extract data from user filled form, using User:
//contains data of a form submitted by a user:
val formData: Map[String, String] = getFormData
val newUser = User(id = randomUuid, firstName = formData.extract[User](_.firstName))
One solution I see is to use a dynamic proxy that extends provided class and remembers what was invoked on him:
def getFieldName[T:Manifest](foo: T => Any) = {
val clazz = implicitly[Manifest[T]].erasure
val proxy = createDynamicProxy(clazz)
foo(proxy)
proxy.lastInvokedMethodName
}
Is there a better way to do it? Is there any lib that implements it already?
This reflective approach takes a case class and invokes its companion apply, calling getField and fetching default args if the field is not in the data.
import scala.reflect.runtime.{currentMirror => cm, universe => uni}
import uni._
def fromXML(xml: Node): Option[PluginDescription] = {
def extract[A]()(implicit tt: TypeTag[A]): Option[A] = {
// extract one field
def getField(field: String): Option[String] = {
val text = (xml \\ field).text.trim
if (text == "") None else Some(text)
}
val apply = uni.newTermName("apply")
val module = uni.typeOf[A].typeSymbol.companionSymbol.asModule
val ts = module.moduleClass.typeSignature
val m = (ts member apply).asMethod
val im = cm reflect (cm reflectModule module).instance
val mm = im reflectMethod m
def getDefault(i: Int): Option[Any] = {
val n = uni.newTermName("apply$default$" + (i+1))
val m = ts member n
if (m == NoSymbol) None
else Some((im reflectMethod m.asMethod)())
}
def extractArgs(pss: List[List[Symbol]]): List[Option[Any]] =
pss.flatten.zipWithIndex map (p => getField(p._1.name.encoded) orElse getDefault(p._2))
val args = extractArgs(m.paramss)
if (args exists (!_.isDefined)) None
else Some(mm(args.flatten: _*).asInstanceOf[A])
}
// check the top-level tag
xml match {
case <plugin>{_*}</plugin> => extract[PluginDescription]()
case _ => None
}
}
The idea was to do something like:
case class User(id: Int = randomUuid, firstName: String, lastName: String)
val user = extract[User]()
That's my own solution:
package utils
import javassist.util.proxy.{MethodHandler, MethodFilter, ProxyFactory}
import org.specs2.mutable._
import javassist.util.proxy.Proxy
import java.lang.reflect.{Constructor, Method}
class DynamicProxyTest extends Specification with MemberNameGetter {
"Dynamic proxy" should {
"extract field name" in {
memberName[TestClass](_.a) must ===("a")
memberName[TestClass](_.i) must ===("i")
memberName[TestClass](_.b) must ===("b")
memberName[TestClass](_.variable) must ===("variable")
memberName[TestClass](_.value) must ===("value")
memberName[TestClass](_.method) must ===("method")
}
}
}
trait MemberNameGetter {
def memberName[T: Manifest](foo: T => Any) = {
val mf = manifest[T]
val clazz = mf.erasure
val proxyFactory = new ProxyFactory
proxyFactory.setSuperclass(clazz)
proxyFactory.setFilter(new MethodFilter {
def isHandled(p1: Method) = true
})
val newClass = proxyFactory.createClass()
var lastInvokedMethod: String = null
val mh = new MethodHandler {
def invoke(p1: Any, p2: Method, p3: Method, p4: Array[AnyRef]) = {
lastInvokedMethod = p2.getName
p3.invoke(p1, p4: _*)
}
}
val constructor = defaultConstructor(newClass)
val parameters = defaultConstructorParameters(constructor)
// val proxy = constructor.newInstance("dsf", new Integer(0))
val proxy2 = constructor.newInstance(parameters: _*)
proxy2.asInstanceOf[Proxy].setHandler(mh)
foo(proxy2.asInstanceOf[T])
lastInvokedMethod
}
private def defaultConstructor(c: Class[_]) = c.getConstructors.head
private def defaultConstructorParameters(constructor: Constructor[_]) = {
val parameterTypes = constructor.getParameterTypes
parameterTypes.map{
case Integer.TYPE => Integer.valueOf(0)
case _ => null
}
}
}
case class TestClass(a: String, i: Int, b: Boolean) {
var variable = "asdf"
val value = "asdfasdfasd"
def method = "method"
}
val mh = new MethodHandler {
def invoke(p1: Any, p2: Method, p3: Method, p4: Array[AnyRef]) = {
lastInvokedMethod = p2.getName
p3.invoke(p1, p4: _*)
}
}
val constructor = defaultConstructor(newClass)
val parameters = defaultConstructorParameters(constructor)
// val proxy = constructor.newInstance("dsf", new Integer(0))
val proxy2 = constructor.newInstance(parameters: _*)
proxy2.asInstanceOf[Proxy].setHandler(mh)
foo(proxy2.asInstanceOf[T])
lastInvokedMethod
}
private def defaultConstructor(c: Class[_]) = c.getConstructors.head
private def defaultConstructorParameters(constructor: Constructor[_]) = {
val parameterTypes = constructor.getParameterTypes
parameterTypes.map{
case Integer.TYPE => Integer.valueOf(0)
case java.lang.Double.TYPE => java.lang.Double.valueOf(0)
case java.lang.Long.TYPE => java.lang.Long.valueOf(0)
case java.lang.Boolean.TYPE => java.lang.Boolean.FALSE
case _ => null
}
}
}
case class TestClass(a: String, i: Int, b: Boolean) {
var variable = "asdf"
val value = "asdfasdfasd"
def method = "method"
}