I have a implicit class which requires a user database. I want to use self-type in implicit class so I can switch implementation of database in testing scope to the mocked version. How do I mix-in database provider in this case? For example, I want user of RuchUser to not worry about having to mix-in UserDatabaseProvider by providing default mix-in. So user can just do User("name").userContext and do the same at testing scope where I will provide default mix-in to use mocked database provider?
case class User(name: String)
object User {
implicit class RichUser(self: User) { this: UserDatabaseProvider =>
def userContext: String = this.getUserContext(self.name)
}
}
// Usage of Rich user should be below as I want to provide already mixed-in implicit
import User._
val context = User("name").uerContext
I think you are overcomplicating quite a bit.
case class User(name: String) {
def context()(implicit db: UserDatabaseProvider): UserContext = {
db.getUserContext(name)
}
}
I would go to further suggest the cake pattern may be more applicable here than using implicits.
class UserService extends UserDatabaseProvider {
def context(user: User): UserContext = getUserContext(user.name)
}
class TestUserService extends UserService with TestDatabase
Let "right-most wins" diamond resolution in Scala do the job for you.
Related
Suppose I have two classes, Person and Business, that are extended by the trait Entity.
trait Entity
case class Person(name: String) extends Entity
case class Business(id: String) extends Entity
Assuming I cannot change Entity, Person and Business (they are in a different file and not to be changed) how can I define a function, say a printEntity, that prints the field name or id, depending on the entity? For example, given instances of Person and Business, how can I do something like this:
object Main extends App {
val person1: Person = Person("Aaaa Bbbb")
val business1: Business = Business("0001")
// How can I do something like this?
person1.printEntity // would call a function that executes println(id)
business1.printEntity // would call a function that executes println(name)
}
Any ideas are appreciated! Sorry for the lack of context, I am still learning!
This is done via so called "extension methods". In scala 2 this is achieved using implicit wrapper class:
trait Entity
case class Person(name: String) extends Entity
case class Business(id: String) extends Entity
implicit class PersonWrapper(val p: Person) extends AnyVal {
def printEntity(): Unit = {
println(p.name)
}
}
implicit class BusinessWrapper(val b: Business) extends AnyVal {
def printEntity(): Unit = {
println(b.id)
}
}
val person1: Person = Person("Aaaa Bbbb")
val business1: Business = Business("0001")
person1.printEntity()
business1.printEntity()
// prints:
//Aaaa Bbbb
//0001
Note, x.printEntity can be called without parentheses, but, by convention, methods with Unit result type and side effects should be called with explicit empty parentheses.
UPD: As #DmytroMitin pointed out, you should extend implicit wrapper classes from AnyVal. This allows the compiler to avoid actually allocating wrapper class instances at runtime, improving performance.
I'm using Play-Slick versions 2.5.x and 3.1.x respectively. I use Slick's code generator and produce the Slick model from an existing database. Actually I'm shy to admit that I'm DB-design driven and not class-design driven.
This is the initial setup:
Generated Slick model under generated.Tables._
Generic Slick dao implementation
Service layer that builds on top of the Generic Slick dao
These are the forces behind the pattern which I temporary called "Pluggable Service" because it allows plugging in the service layer functionality to the model:
Play's controllers and views must only see the Service layer (and not the Dao's) e.g. UserService
Generated model e.g. UserRow is expected to comply to business layer interfaces e.g. Deadbolt-2's Subject but not implement it directly. To be able to implement it one needs "too much" e.g. the UserRow model type, the UserDao and potentially some business context.
Some of the UserService methods naturally apply to the model UserRow instance e.g. loggedUser.roles or loggedUser.changePassword
Therefore I have:
generated.Tables.scala Slick model classes:
case class UserRow(id: Long, username: String, firstName: String,
lastName : String, ...) extends EntityAutoInc[Long, UserRow]
dao.UserDao.scala Dao extensions and customizations specific to the User model:
#Singleton
class UserDao #Inject()(protected val dbConfigProvider: DatabaseConfigProvider)
extends GenericDaoAutoIncImpl[User, UserRow, Long] (dbConfigProvider, User) {
//------------------------------------------------------------------------
def roles(user: UserRow) : Future[Seq[Role]] = {
val action = (for {
role <- SecurityRole
userRole <- UserSecurityRole if role.id === userRole.securityRoleId
user <- User if userRole.userId === user.id
} yield role).result
db.run(action)
}
}
services.UserService.scala service that facades all user operations to the rest of the Play application:
#Singleton
class UserService #Inject()(auth : PlayAuthenticate, userDao: UserDao) {
// implicitly executes a DBIO and waits indefinitely for
// the Future to complete
import utils.DbExecutionUtils._
//------------------------------------------------------------------------
// Deadbolt-2 Subject implementation expects a List[Role] type
def roles(user: UserRow) : List[Role] = {
val roles = userDao.roles(user)
roles.toList
}
}
services.PluggableUserService.scala finally the actual "Pluggable" pattern that dynamically attaches service implementations to the model type:
trait PluggableUserService extends be.objectify.deadbolt.scala.models.Subject {
override def roles: List[Role]
}
object PluggableUserService {
implicit class toPluggable(user: UserRow)(implicit userService: UserService)
extends PluggableUserService {
//------------------------------------------------------------------------
override def roles: List[Role] = {
userService.roles(user)
}
}
Finally one can do in the controllers:
#Singleton
class Application #Inject() (implicit
val messagesApi: MessagesApi,
session: Session,
deadbolt: DeadboltActions,
userService: UserService) extends Controller with I18nSupport {
import services.PluggableUserService._
def index = deadbolt.WithAuthRequest()() { implicit request =>
Future {
val user: UserRow = userService.findUserInSession(session)
// auto-magically plugs the service to the model
val roles = user.roles
// ...
Ok(views.html.index)
}
}
Is there any Scala way that could help not having to write the boilerplate code in the Pluggable Service object? does the Pluggable Service name makes sense?
One of the common variant may be a parent trait for your controllers that has something along these lines:
def MyAction[A](bodyParser: BodyParser[A] = parse.anyContent)
(block: (UserWithRoles) => (AuthenticatedRequest[A]) => Future[Result]): Action[A] = {
deadbolt.WithAuthRequest()(bodyParser) { request =>
val user: UserRow = userService.findUserInSession(session)
// this may be as you had it originally
// but I don't see a reason not to
// simply pull it explicitly from db or
// to have it in the session together with roles in the first place (as below UserWithRoles class)
val roles = user.roles
block(UserWithRoles(user, roles))(request)
}
The elephant in the room here is how you get userService instance. Well you would need to explicitly require it in your controller constructor (in the same way you do with DeadboltActions). Alternatively you may bundle DeadboltActions, UserService and what else into one class (e.g. ControllerContext?) and inject this single instance as one constructor parameter (but that's probably another discussion...).
After that your controller code would be like this:
def index = MyAction() { implicit user => implicit request =>
Future {
// ...
Ok(views.html.index)
}
}
both user and request is implicit which helps to pass into into inner parts of your application (which is often the case - you bring user object to perform some business logic).
It doesn't get rid of your PluggableUserService per se (logic is still there) but it may help you to easier reuse same logic everywhere in your controllers (as in my experience, you need to have both User together with Roles more often than not in any real application).
EDIT: I got a feeling I didn't quite get your question. You want to avoid boilerplate in PluggableUserService or you want to avoid scattering this conversion with use of PluggableUserService everywhere, in every controller (IMHO 2nd option is something to be avoided)?
I have a trait that's implemented by a large number of classes, and I'd like to use the names of the classes that implement this trait at runtime, but with as much code centralized as possible.
Specifically, in my code, I'm using tokens to represent classes to be initialized at runtime. The tokens carry configuration, and the actual class is instantiated as needed via the token, combined with run-time information. For linking with resources outside of my app, I want to be able to access the name of the class for which a token is defined. See the example:
trait Token[Cls] {
val className = ???
// Example generic method depending on final class name
def printClassName = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
So, I'm trying to implement className. Ideally, I can pull this information once at compile time. How can I do this, while keeping boilerplate code out of ClassA? Although, if I can drop the type parameter and get the name of the class implementing the Token trait at runtime, that's great too.
Due to Type Erasure Cls is not available on runtime anymore. To get the informations at runtime, you need to use a TypeTag (in your case a ClassTag).
Your code could look like this:
import scala.reflect._
trait Token[Cls] {
def className(implicit ct: ClassTag[Cls]) = ct.runtimeClass.getName
// Example generic method depending on final class name
def printClassName(implicit ct: ClassTag[Cls]) = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
or if it is possible for you to let Token be an class, you could use the ClassTag context bounds:
import scala.reflect._
class Token[Cls: ClassTag] {
def className = classTag[Cls].runtimeClass.getName
// Example generic method depending on final class name
def printClassName = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
For more informations on TypeTags/ClassTags see Scala: What is a TypeTag and how do I use it?
I was wondering if anyone has any experience with creating a type-parametrized type hierarchy? I am fairly certain this is acheivable as a result of scala's pseudo-unification of packages & static objects.
The specific use case I have in mind is parametrizing an id type over an application framework so you can use your choice of int/long/java.util.UUID/BSONId/whatever. Consider as a rough example:
package foolib.generic
trait GenEntity[I] { def id: I }
trait GenRepository[I] { def getById(id: I): GenEntity[I] }
trait FooTaxonomy[I] {
type Entity = GenEntity[I]
type Repository = GenRepository[I]
object subpackage extends generic.subpackage.SubpackageTaxonomy[I]
}
You would then configure the hierarchy for use in a project with something like:
package object myprj {
object foolib extends foolib.generic.FooTaxonomy[java.util.UUID]
// Whee!
val someEntity = new myprj.foolib.Entity(java.util.UUID.randomUUID())
}
Are there any reasons this is a spectacularly bad idea? Any pitfalls/etc I should be aware of?
This approach would work but you may encounter problems when the number of type parameters increases. Perhaps a solution would be to use abstract type members instead of type parameters.
Another approach is to use the cake pattern which I think provides a better solution in your case. The exact logic of your code eludes me a bit, so this rewrite may not entirely represent your intention:
package foolib.generic
//defines common types used by all modules
trait CoreModule {
type Id // abstract type, not commited to any particular implementation
}
//module defining the EntityModule trait
trait EntityModule { this: CoreModule => //specifying core module as a dependency
trait GenEntity {
def id: Id
}
def mkEntity(id: Id): Entity //abstract way of creating an entity
}
//defines the GenRepository trait
trait RepositoryModule { this: EntityModule with CoreModule => //multiple dependencies
trait GenRepository {
def getById(id: Id): GenEntity
}
val repository: GenRepository //abstract way of obtaining a repository
}
//concrete implementation for entity
trait EntityImplModule extends EntityModule { this: CoreModule =>
case class Entity(val id: Id) extends GenEntity
def mkEntity(id: Id) = Entity(id)
}
//modules that provides a concrete implementation for GenRepository
trait RepositoryImplModule extends RepositoryModule { this: CoreModule with EntityModule =>
object RepositoryImpl extends GenRepository {
def getById(id: Id) = mkEntity(id)
}
}
//this unifies all your modules. You can also bind any dependencies and specify any types
object Universe
extends CoreModule
with EntityImplModule
with RepositoryImplModule {
type Id = java.util.UUID
val repository = RepositoryImpl
def mkEntity(id: Id) = Entity(id)
}
//usage
object Main {
import Universe._
import java.util.UUID
val entity = repository.getById(UUID.randomUUID())
println(entity.id)
}
This achieves your goal of creating an implementation independent of the concrete type Id and it also provides a nice way to do dependency injection.
The modules which provide a concrete implementation for GenRepository, for instance, may require a concrete type for Id. You can very well create another module which binds Id to a concrete type and make the RepositoryImplModule depend on the former module, thus specifying that this concrete implementation of GenRepository will work only for a certain type of ids.
The Cake pattern is very powerful and has many variations. This video explains it quite well, I recommend you watch it if you are interested in this solution:
Cake Pattern: The Bakery from the Black Lagoon
I'm using a Logging trait in my application and I'm curious whether it's possible to access a protected variable from the Logging trait.
This is what I have:
class MyClass extends ExternalTrait with Logging
trait ExternalTrait {
protected val protectedVar = "secret?"
}
trait Logging {
if(this.isInstanceOf[OtherTrait])
this.asInstanceOf[OtherTrait].protectedVar
}
but the access to the protected variable is restricted when accessing in this manner. Is there some other way to access the protectedVar from the Logging trait?
Many thanks.
If you definitely know that Logging later is mixed in to ExternalTrait you can place a self reference:
trait Logging { this: ExternalTrait =>
val value = protectedVar
}
Of course, if there can be logging traits which do not extend/mixin other traits self references are not suitable. In such a case I would subclass Logging to handle the different behavior.
trait Logging
trait StandAloneLogging extends Logging
trait BasedOnLogging extends Logging { this: ExternalTrait =>
val value = protectedVar
}