Skip to content

Commit

Permalink
Relagate filter methods to a FilteringDirective subtype. This
Browse files Browse the repository at this point in the history
isolates other directives from the no-op filter strangeness, and opens
up some possibilities of useful filtering.
  • Loading branch information
Nathan Hamblen committed Sep 8, 2014
1 parent c7c18e6 commit ca98438
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions directives/src/main/scala/directives/Directive.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,24 @@ extends (HttpRequest[T] => Result[R, A]) {
def flatMap[TT <: T, RR >: R, B](f:A => Directive[TT, RR, B]):Directive[TT, RR, B] =
Directive(r => run(r).flatMap(a => f(a)(r)))

/** Doesn't filter. Scala requires something to be defined for pattern matching in for
expressions, and we do use that. */
def withFilter(f:A => Boolean): Directive[T, R, A] = this
/** Doesn't filter. Scala requires something to be defined for pattern matching in for
expressions, and we do use that. */
def filter(f:A => Boolean): Directive[T, R, A] = this

def orElse[TT <: T, RR >: R, B >: A](next: => Directive[TT, RR, B]): Directive[TT, RR, B] =
Directive(r => run(r).orElse(next(r)))

def | [TT <: T, RR >: R, B >: A](next: => Directive[TT, RR, B]): Directive[TT, RR, B] =
orElse(next)

def and[TT <: T, E, B, RF](other: => Directive[TT, JoiningResponseFunction[E,RF], B])
(implicit ev: R <:< JoiningResponseFunction[E,RF]) =
new Directive[TT, JoiningResponseFunction[E,RF], (A,B)] ( req =>
this(req) and other(req)
)
(implicit ev: R <:< JoiningResponseFunction[E,RF]) = {
val runner = (req: HttpRequest[TT]) => this(req) and other(req)
// A `filter` implementation is required for pattern matching, which we
// use to extract joined successes. This is a no-op filter; an improved
// response joining system would make `toResponseFunction` available
// to use here with an empty Seq.
new FilteringDirective[TT, JoiningResponseFunction[E,RF], (A,B)](
runner,
runner
)
}

def &[TT <: T, E, B, RF](other: => Directive[TT, JoiningResponseFunction[E,RF], B])
(implicit ev: R <:< JoiningResponseFunction[E,RF]) = this and other
Expand All @@ -98,6 +98,21 @@ extends (HttpRequest[T] => Result[R, A]) {
}
}

/** Supports filtering by requiring a handler for when success is filtered away.
The onEmtpy handler may produce a success or failure; typically the latter. */
class FilteringDirective[-T, +R, +A](
run: HttpRequest[T] => Result[R, A],
onEmpty: HttpRequest[T] => Result[R, A]
) extends Directive[T,R,A](run) {
def withFilter(filt: A => Boolean): Directive[T, R, A] =
new FilteringDirective({ req =>
run(req).flatMap { a =>
if (filt(a)) Result.Success(a)
else onEmpty(req)
}
}, onEmpty)
}

class JoiningResponseFunction[E,A]
(val elements: List[E], toResponseFunction: Seq[E] => ResponseFunction[A])
extends ResponseFunction[A] {
Expand Down

0 comments on commit ca98438

Please sign in to comment.