diff --git a/src/main/scala/com/abraxas/slothql/mapper/ScalaExpr.scala b/src/main/scala/com/abraxas/slothql/mapper/ScalaExpr.scala index 0e9942fb..8f827408 100644 --- a/src/main/scala/com/abraxas/slothql/mapper/ScalaExpr.scala +++ b/src/main/scala/com/abraxas/slothql/mapper/ScalaExpr.scala @@ -84,7 +84,12 @@ object ScalaExpr { protected trait FieldSelectionOps extends Dynamic { expr: ScalaExpr => - def selectDynamic(k: String)(implicit ev: Syntax.HasField[Source, Symbol @@ k.type]): SelectField[Source, k.type, ev.Value] = SelectField(k) + def selectDynamic[V, A <: Arrow](k: String)( + implicit + ev0: Syntax.HasField.Aux[Target, Symbol @@ k.type, V], + ev1: expr.type <:< A, // using `expr.type` directly in `compose` would require _existential types_ + compose: Arrow.Compose[SelectField[Target, k.type, V], A] + ): compose.Out = compose(SelectField(k), expr) } object Syntax { diff --git a/src/test/scala/com/abraxas/slothql/TestArrows.scala b/src/test/scala/com/abraxas/slothql/TestArrows.scala index 6b40eb85..390d00f5 100644 --- a/src/test/scala/com/abraxas/slothql/TestArrows.scala +++ b/src/test/scala/com/abraxas/slothql/TestArrows.scala @@ -99,6 +99,12 @@ object FunctorsTest { // ]{type Source = Book;type Target = Option[String]} // = MBind(SelectField(pseudonym)) ∘ SelectField(author) + val selIsbn = ScalaExpr[Book].meta.isbn + // Arrow.Composition[ + // ScalaExpr.SelectField[Meta, isbn, String], + // ScalaExpr.SelectField[Book, meta, Meta] + // ]{type Source = Book;type Target = String} + // = SelectField(isbn) ∘ SelectField(meta) // val mapped0 = Functor.map(sel2 ∘ sel1).to[GraphPath] // val mapped1 = Functor.map(sel3 ∘ (sel2 ∘ sel1)).to[GraphPath] diff --git a/src/test/scala/com/abraxas/slothql/test/models/Book.scala b/src/test/scala/com/abraxas/slothql/test/models/Book.scala index dccddc3a..5b7ff4d8 100644 --- a/src/test/scala/com/abraxas/slothql/test/models/Book.scala +++ b/src/test/scala/com/abraxas/slothql/test/models/Book.scala @@ -5,9 +5,10 @@ import shapeless.syntax.singleton._ import com.abraxas.slothql.mapper.{ GraphRepr, Schema } -case class Book(author: Option[Author], pages: List[Page]) +case class Book(author: Option[Author], pages: List[Page], meta: Meta) case class Author(name: String, pseudonym: Option[String]) case class Page(text: String) +case class Meta(isbn: String) object Book { object PageListRepr extends GraphRepr.Relation { @@ -31,16 +32,23 @@ object Book { type Labels = Witness.`"Book"`.T :: HNil type Fields = HNil type Outgoing = Witness.`'author`.Field[GraphRepr.Node.Optional[Author.AuthorRepr.type]] :: - Witness.`'pages` .Field[PageListRepr.type] :: HNil + Witness.`'pages` .Field[PageListRepr.type] :: + Witness.`'meta` .Field[Meta.MetaRepr.type] :: HNil lazy val Labels: Labels = "Book".narrow :: HNil lazy val Fields: Fields = HNil lazy val Outgoing: Outgoing = 'author ->> GraphRepr.Node.Optional(Author.AuthorRepr) :: - 'pages ->> PageListRepr :: HNil + 'pages ->> PageListRepr :: + 'meta ->> Meta.MetaRepr :: HNil lazy val labels: List[String] = List("Book") - lazy val fields: Map[String, GraphRepr.Property] = Map("author" -> GraphRepr.Property[String]) - lazy val outgoing: Map[String, GraphRepr.Relation] = Map("pages" -> PageListRepr) + lazy val fields: Map[String, GraphRepr.Property] = Map() + // TODO ========================================================================================================= + lazy val outgoing: Map[String, GraphRepr.Relation] = ??? /*Map( + "author" -> GraphRepr.Node.Optional(Author.AuthorRepr), + "pages" -> PageListRepr, + "meta" -> Meta.MetaRepr + )*/ } implicit def pagesSchema: Schema.Aux[List[Page], PageListRepr.type] = Schema.defineFor[List[Page]](PageListRepr) @@ -79,4 +87,18 @@ object Page { lazy val outgoing: Map[String, GraphRepr.Relation] = Map() } implicit def pageSchema: Schema.Aux[Page, PageRepr.type] = Schema.defineFor[Page](PageRepr) +} + +object Meta { + object MetaRepr extends GraphRepr.Node { + type Labels = Witness.`"Meta"`.T :: HNil + type Fields = Witness.`'isbn`.Field[GraphRepr.Property.Aux[String]] :: HNil + type Outgoing = HNil + val Labels: Labels = "Meta".narrow :: HNil + val Fields: Fields = 'isbn ->> GraphRepr.Property[String] :: HNil + val Outgoing: Outgoing = HNil + val labels: List[String] = List("Meta") + val fields: Map[String, GraphRepr.Property] = Map("isbn" -> GraphRepr.Property[String]) + val outgoing: Map[String, GraphRepr.Relation] = Map() + } } \ No newline at end of file