Search code examples
clojureclojurescriptom

Om Next's query->ast and ast->query functions


According to Om Next's documentation:

query->ast

(om.next/query->ast '[(:foo {:bar 1})])

Given a query expression return the AST.

ast->query

(om.next/ast->query ast)

Given a query expression AST, unparse it into a query expression.

Question: Why would one need these functions? That is, why would one need to directly manipulate a query abstract syntax tree (which I'm assuming are clojure maps that represent a query tree, along with some meta data) in om next?


Solution

  • There are some scenarios where you need to manipulate the query ast directly. In remote parsing mode, the parser expects your read functions to return either {:remote-name true } or a (possibly modified) {:remote-name AST-node} (which comes in as :ast in env). Most often you'll have to modify the AST to restructure it or add some data.

    Example 1: You have a query: [{:widget {:list [:name :created]}}] The :widget part is pure UI related, your server doesn't need to know it exists, it only cares/knows about the :list. Basically you'll have to modify the AST in the parser:

    (defmethod read :list
      [{:keys [ast query state]} key _ ]
      (let [st @state]
        {:value (om/db->tree query (get st key) st)
         :remote (assoc ast :query-root true)}))
    

    If you use om/process-rootsin your send function, it'll pick up the :query-root out of the ast and rewrite the query from [{:widget {:list [:name :created]}}] to [{:list [:name :created]}].

    Example 2: Another example would be when you want to mutate something at a remote:

    (defmethod mutate 'item/update
      [{:keys [state ast]} key {:keys [id title]}]
      {:remote (assoc ast :params {:data {:id id :title title })})
    

    Here you need to explicitly tell Om to include the data you want to send in the AST. At your remote you then pick apart :data to update the title at the given id

    Most of the time you won't use the functions you described in your questions directly. The env available in every method of the parser has the ast in it.