SORM Persisted 'id' undefined - scala

I am just trying to learn SORM and am playing with what I think is some simple sample code. To whit:
case class Book(var author:String, var title:String);
object Db extends Instance(
entities = Set(Entity[Book]()),
url = "jdbc:h2:mem:test",
user = "",
password = "",
initMode = InitMode.Create
)
And then:
val b : Book with Persisted = Db.save( Book("foo","bar") )
When attempting to compile this, I get:
[error] /Users/rjf/IdeaProjects/PlayTest/app/controllers/Application.scala:22: type mismatch;
[error] found : models.Book
[error] required: sorm.Persisted with models.Book
[error] val b : Book with Persisted = Db.save( Book("foo","bar") )
[error] ^
If I change the Book declaration to:
case class Book(var author:String, var title:String) extends Persisted;
I then get:
[error] /Users/rjf/IdeaProjects/PlayTest/app/models/Book.scala:17: class Book needs to be abstract, since:
[error] it has 2 unimplemented members.
[error] /** As seen from class Book, the missing signatures are as follows.
[error] * For convenience, these are usable as stub implementations.
[error] */
[error] def id: Long = ???
[error] def mixoutPersisted[T]: (Long, T) = ???
[error] case class Book(var author:String, var title:String) extends Persisted;
[error] ^
Apologies for the newbie question. No doubt that the fact I'm learning Scala at the same time is a contributing factor.

To solve your issue, just remove the explicit type annotation:
val b = Db.save( Book("foo","bar") )
Don't worry, you'll still be able to access the same interface as Book with Persisted.
As to why this happens, this seems to be a bug of Scala, and it's been reported.
A sidenote
Don't use vars in case class declaration. Immutability is the whole point of case classes. The correct declaration would be:
case class Book(author:String, title:String)
which is the same as
case class Book(val author:String, val title:String)

Related

play slick updating enumeration column

I'm having trouble figuring out how to update a column with type enumeration using play-slick.
Here's my enum and case class:
object TestStatus extends Enumeration {
type TestStatus = Value
val Status1 = Value("Status1")
}
case class Test (
id: String,
status: TestStatus
)
and the table mapping:
class Tests(tag: Tag) extends Table[Test](tag, "tests") {
implicit val statusColumn = MappedColumnType.base[TestStatus, String](_.toString, TestStatus.withName)
override def * = (id, status) <> ((Test.apply _).tupled, Test.unapply)
val id = column[String]("id", 0.PrimaryKey)
val status = column[TestStatus]("status")
}
when I try to go and update a Tests row, I get an error:
object TestQueries extends TableQuery[Tests](new Tests(_)) {
def updateStatus(id: String, newStatus: TestStatus) = {
TestQueries.filter(_.id === id).map(_.status).update(newStatus)
}
}
[error] Slick does not know how to map the given types.
[error] Possible causes: T in Table[T] does not match your * projection,
[error] you use an unsupported type in a Query (e.g. scala List),
[error] or you forgot to import a driver api into scope.
[error] Required level: slick.lifted.FlatShapeLevel
[error] Source type: slick.lifted.Rep[models.TestStatus.Value]
[error] Unpacked type: T
[error] Packed type: G
[error] TestQueries.filter(_.id === id).map(_.status).update(newStatus)
[error] ^
IntelliJ is showing that TestQueries.filter(_.id === id).map(_.status) has type Query[Nothing, Nothing, Seq], which makes me think the problem is with the specific column rather than with the update function.
Updating the id works fine using the same structure.
You need to define the custom column type of TestStatus.Value. This is how slick allows you to build a custom column type by mapping it to an already supported type:
implicit def testStatCT: BaseTypedType[TestStatus.Value] =
MappedColumnType.base[TestStatus.Value, String](
enum => enum.toString, str => TestStatus.withName(str)
)
this implicit needs to be imported wherever implicit resolutions such as the one in your example fail (or better yet defined in the TestStatus object so that it's always available) this way slick can have evidence that TestStatus.Value is a BaseTypedType which basically just means that something is a supported column type.
For further read on column mapping you can look at Slick Documentation

scala inherited value do not find

Scala version 2.11.8
I have parent class
abstract class FR(externalId:String, code:String, message:String) extends Serializable {
val this.externalId=externalId;
val this.code = code;
val this.message = message;
def toString:String={
return "FRworks";
}
}
The child class is:
class RD extends FR {
def this(lpTransaction:LPTransaction)={
externalId =lpTransaction.getField("somethinghere").toString
...
}
}
The error is:
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading project definition from F:\workspace\frankcheckAPI\project
[info] Set current project to frankcheckapi (in build file:/F:/workspace/frankcheckAPI/)
[info] Compiling 20 Scala sources to F:\workspace\frankcheckAPI\target\scala-2.11\classes...
[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\fraudcheck\RD.scala:9: 'this' expected but identifier found.
[error] externalId =lpTransaction.getField("somethinghere").toString
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
when I add this in front of externalId the error still:
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading project definition from F:\workspace\frankcheckAPI\project
[info] Set current project to frankcheckapi (in build file:/F:/workspace/frankcheckAPI/)
[info] Compiling 20 Scala sources to F:\workspace\frankcheckAPI\target\scala-2.11\classes...
[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\fraudcheck\ReDFraudCheckResponse.scala:9: '}' expected but '.' found.
[error] this.externalId =lpTransaction.getField("somethinghere").toString
[error] ^
[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\fraudcheck\ReDFraudCheckResponse.scala:12: eof expected but '}' found.
[error] }
[error] ^
[error] two errors found
[error] (compile:compileIncremental) Compilation failed
Your code is very Java-influenced. There are couple of things wrong here; when you fix the obvious ones like missing class parameters in RD it boils down to not being able to reassign to val.
Let me give you an improved, Scala-fied version of the whole code.
abstract class FR(val externalId: String, val code: String, val message: String) extends Serializable
// dummy class
class LPTransaction {
def getField(s: String) = s
}
class RD(externalId: String, code: String, message: String) extends FR(externalId, code, message) {
def this(lpTransaction: LPTransaction) = {
this(lpTransaction.getField("somethinghere").toString, "defaultCode", "defaultMessage")
}
println(externalId)
}
val a = new RD(new LPTransaction) // prints "somethinghere"
Main improvements are:
You don't need private fields to be populated using arguments in the constructor. Scala favors immutability. Make your class arguments "vals", this means they will be available as public fields (instead of getters you will access them directly; this is contrary to OOP's encapsulation principle, but here it's ok because nobody can mess with them anyway since they are immutable; they may only be fetched)
Your subclass RD should be taking same fields as parameters as its parent class. Of course, you can then define an auxiliary constructor that takes only LPTransaction, but then you need to feed the parent class with some default values for the other parameters.
The rest kind of follows from this. I added the dummy implementation of LPTransaction to be able to compile. I also threw in a println statement in RD class just for the sake of example. Feel free to ask if something's not clear.
//scala automatically generates getters for passed in params. No need to set them explicitly. For immutable params use val, for mutable use var
abstract class FR(var externalId:String, val code:String, val message:String) extends Serializable {
//need to use override annotation for superclass methods
override def toString:String={
return "FRworks";
}
}
// notice how constructor parameters are passed to the base class when defining the child class.
class RD extends FR("someID","code","msg") {
def printId() = println(externalId)
}
val x = new RD
x.externalId = "new ID" //works because externalId is var (mutable)
x.code = "new code" //error because code is val (immutable)
x.printId //correctly prints the external id: someID

Scala value has incompatible type?

I am still new enough to Scala that the typing system is destroying me. I haven't yet thought of a solution or discovered a pattern that gets around this particular problem that I am trying to solve. Consider the following program:
ShapeType.scala
package models
abstract class ShapeType {
val themes: ShapeThemes[ShapeTheme] // I think this is where the problem is...?
}
class CircleShapeType extends ShapeType {
val themes = CircleShapeThemes
}
object CircleShapeType extends CircleShapeType
ShapeThemes.scala
package models
abstract class ShapeThemes[T <: ShapeTheme] {
val themes: List[T]
}
class CircleShapeThemes extends ShapeThemes[CircleShapeTheme] {
val themes = List(
new CircleShapeTheme,
new CircleShapeTheme,
new CircleShapeTheme
)
}
object CircleShapeThemes extends CircleShapeThemes
ShapeTheme.scala
package models
class ShapeTheme
class CircleShapeTheme extends ShapeTheme
When I attempt to compile the program (using sbt), I get the following error:
[error] /Users/mjs/Projects/sandbox/shape-types/src/main/scala/ShapeType.scala:8: overriding value themes in class ShapeType of type models.ShapeThemes[models.ShapeTheme];
[error] value themes has incompatible type
[error] val themes = CircleShapeThemes
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 2 s, completed Mar 14, 2015 5:08:43 PM
However, as far as I can tell, CircleShapeThemes is a ShapeThemes[ShapeTheme]. What am I missing?
CircleShapeThemes is not a ShapeThemes[ShapeTheme], it's a ShapeThemes[CircleShapeTheme].
"But", you may object, "a CircleShapeTheme is a ShapeTheme! Indeed, but that subclass relationship isn't propagated by default. You have to ask for it by making the type parameter covariant: abstract class ShapeThemes[+T <: ShapeTheme]

why does the slick can not store Option[String]?

I use slick 2.0 rc1 in my playframework 2.2 project
my talbe code is:
case class Resource(id: Option[Long] = None, owner: UserId, types: String)
// The static object that does the actual work - note the names of tables and fields in H2 are case sensitive and must be all caps
object Resources extends Table[Resource]( "RESOURCE") {
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def owner = column[UserId]("Owner")
def types = column[String]("Type")
def withuser = foreignKey("User_FK", owner, Users)(_.id)
// Every table needs a * projection with the same type as the table's type parameter
def * = id.? ~ owner ~ types <> (Resource, Resource.unapply _)
}
the output error is:
[info] Compiling 16 Scala sources and 2 Java sources to C:\assigment\slick-advan
ced\target\scala-2.10\classes...
[error] C:\assigment\slick-advanced\app\models\Resource.scala:12: overloaded met
hod constructor Table with alternatives:
[error] (_tableTag: scala.slick.lifted.Tag,_tableName: String)play.api.db.slic
k.Config.driver.Table[models.Resource] <and>
[error] (_tableTag: scala.slick.lifted.Tag,_schemaName: Option[String],_tableN
ame: String)play.api.db.slick.Config.driver.Table[models.Resource]
[error] cannot be applied to (String)
[error] object Resources extends Table[Resource]( "RESOURCE") {
[error] ^
I know on document it like:
object Resources(tag: Tag) extends TableTable[(Long, UserId, String)](tag, "RESOURCE") {
but after I change it, it still have error:
[error] C:\assigment\slick-advanced\app\models\Resource.scala:12: traits or obje
cts may not have parameters
[error] object Resources(tag: Tag) extends TableTable[(Long, UserId, String)](ta
g, "RESOURCE") {
[error] ^
[error] one error found
Check out the Scaladoc for Table for the constructors:
new Table(_tableTag: Tag, _tableName: String)
new Table(_tableTag: Tag, _schemaName: Option[String], _tableName: String)
The compiler is telling you that you have those choices but are using neither. You construct your instance of Table called Resources with just a String. As you can see, that isn't an option. No pun intended.
The documentation shows that your declaration should look more like this:
class Resources(tag: Tag) extends Table[(Long, UserId, String)](tag, "RESOURCE") {
...
}
val Resources = TableQuery[Resources]

Specifying a return type for Slick's MappedProjection

I'm using the PlayFramework 2.1.1 in combination with Slick 1.0.1 and the Play-Slick-Plugin 0.3.2.
Defining an abstract class that enforces my models to implement a "forInsert"-Mapper fails because I'm unable to specify the proper return type. My current definition results in the compile error below but I'm simply unable to track down this issue and provide the correct type.
import play.api.db.slick.Config.driver.KeysInsertInvoker
abstract class Model[M]( val table: String ) extends Table[M]( table )
{
def id = column[Int]( "id", O.PrimaryKey, O.AutoInc )
def forInsert: KeysInsertInvoker[M, Int]
}
object Course extends Model[Course]( "course" )
{
...
def forInsert = name ~ room <> ( apply _, unapply _ ) returning id
}
[error] Course.scala:27: polymorphic expression cannot be instantiated to expected type;
[error] found : [RU]play.api.db.slick.Config.driver.KeysInsertInvoker[model.Course,RU]
[error] required: play.api.db.slick.Config.driver.KeysInsertInvoker[model.Course,Int]
[error] def forInsert = name ~ room <> ( apply _, unapply _ ) returning id
[error] ^
[error] one error found
[error] (sample/compile:compile) Compilation failed
[error] Total time: 3 s, completed 18.06.2013 03:38:24
abstract class Model[M]( val table: String ) extends Table[M]( table )
{
def id = column[Int]( "id", O.PrimaryKey, O.AutoInc )
def forInsert: scala.slick.driver.BasicInvokerComponent#KeysInsertInvoker[M, Int]
}
Not that difficult. Printing a getClass from the implementation solved the mystery quite easily. An idea I didn't come up with yesterday night.