I'm trying to create a generic database insertion method in Scala using the Slick and Play! frameworks. This involves passing in a generic Form instance and the model object that it's associated to. There are two problems I'm running into that are driving me nuts at the moment:
- How do I instantiate a generic type?
- How do I dynamically generate the parameters of that generic type from generic form binding?
Code so far
/**
* Template method for accessing a database that abstracts out
* Database.forDataSource(DB.getDataSource()) withSession {}
* and actual form vals; will allow for anonymous Form declarations.
*/
def dbAccessThatUsesAForm[I <: AnyRef, T <: Table[I]](
f: Form[Product], // a Form of some generic tuple or mapping
t: T, // a Slick table to insert I objects into
i: Class[I] // the actual class that I belongs to (maybe not needed)
)(
request: SecuredRequest[AnyContent] // this is a SecureSocial auth. thing
): Boolean = {
f.bindFromRequest((request.request.body.asFormUrlEncoded).getOrElse(Map())).fold(
errors => {
logger.error(t.toString + "was not bound to " + t.toString + "'s Form correctly")
false
},
success => {
t.insert(new I(someParamsThatIHaveNoIdeaWhereToStart)) // DOES NOT WORK
true
}
)
}
On one
type not found: I
At this point I think I'm deeply misunderstanding something about Scala generics and considering using dependency injection as a solution. Maybe pass in a function that binds a class to this method, and call that within my method? But I already have an Injector
defined in Global.scala
that follows this post... Dependency injection here is based on a module... but injection here isn't based on whether I'm in production or in testing...
On two
Play Forms can take tuples for their field mappings. So I tried looking up how to describe generic tuple types . Therefore I surmised that I'd be passing in a Form[Product]
(API for Product and Form) instead of Form[_]
, and doing something like:
(the thing in the for loop won't work because productArity
isn't actually part of mapping )
for( i = 1 to f.mapping.productArity ) { // pretty sure this won't work.
// generate the parameters and store them to some val by calling smth like
val store Params += success.productElem(i)
}
As you can see, I'm quite lost as to
- how to get the number of fields in a Form because a Form is actually composed of a
Seq[Mapping]
and
- how in the world I'd store dynamically generated parameters.
Do constructors receive parameters as a tuple? Is there a sort of Parameter object I could pass in to a generic class instantiator?