Instead of defining Step superschema can you simply do:
(s/validate something (get-schema step))
??
If you need more than that, for example, if you need a named schema to use
it in function signatures, then I think you have two options:
1- Define a superschema just like in your example, but using the
multimethod instead of a literal:
(defmulti get-schema :type)
(defmethod get-schema :http [v] {:url s/Str})
(defmethod get-schema :delay [v] {:seconds s/Int})
(def Step
(apply s/conditional
(flatten (for [type (keys (methods get-schema))]
[#(= (:type %) type)
(get-schema {:type type})]))))
The problem here is you need to have all the methods already defined by
your api users at the moment of defining the Step "superschema".
2- Generalize the problem, you need to define an Schema that resolves
dinamically to another based on the value. s/conditional does something
like that but is not sufficient. I think is an uncovered corner case in
Prismatic Schema, you can try doing something like this:
(defrecord SchemaResolver [resolve-fun]
s/Schema
(walker [this]
(fn [value] (s/walker (resolve-fun value))))
(explain [this]
;; not implemented
))
(defmulti get-schema :type)
(def Step (SchemaResolver. get-schema))
;; defmethods can be next,
;; because the schema will be resolved dinamically on each
;; validation.
(defmethod get-schema :http [v] {:url s/Str})
(defmethod get-schema :delay [v] {:seconds s/Int})
But this will not work because Prismatic Schema does some tricks with
dynamic binding when calling walker, so you can't simply delegate this way.
Maybe you need to discuss this in the ticket.
Saludos,
Nahuel Greco.
On Mon, Aug 25, 2014 at 7:41 AM, Laurens Van Houtven <[email protected]> wrote:
> Hi Nahuel,
>
>
> On Saturday, August 23, 2014 7:23:42 PM UTC+2, nahuel wrote:
>>
>> what about:
>>
>> (defmulti step-handler :type)
>> (defmulti get-schema :type) ;; returns the schema
>>
>> And make your users implement both? Remember schemas are first-class
>> values.
>>
>
> The difficulty I'm having is figuring out how to then embed these schemas
> into another schema. (The reason I want *that* is because these steps are
> composed into different schemas, and I'd like to check the superschema.)
> Ideally I would end up with something like:
>
> (def Step
> (s/conditional
> #(= (:type %) :http) {:the :http :schema :here}
> #(= (:type %) :delay) {:the :delay :schema: :here}))
>
> ... except with the keys and schemas coming out of the multimethod (or
> whatever) instead of being a literal :)
>
> I guess I could do that with some extended macrology hackery for now; if
> my defstep macro stashes all of the schemas in a ref somewhere, I can then
> expand to the above code example :)
>
> I've created a ticket for this on prismatic/schema:
> https://github.com/Prismatic/schema/issues/140
>
> thanks again,
> lvh
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to [email protected]
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.