Reputation: 1
This is the structure that I found in cerner/clara-rules repo's test case:
(def external-rules "[{:name \"cold-query\", :params #{:?l}, :lhs [{:type clara.rules.testfacts.Temperature, :constraints [(< temperature 50) (= ?t temperature) (= ?l location)]}]}]")
I'm writting but in a rules.edn
file. When required I read it and it to session with mk-session
. In this Im able write basic rules and it is getting fired as required. But the issue is I want to take to next step where I want to access the facts in the session and modify it.
Let say there is a defrecord that is inserted as a fact after creating a session. And Im able to insert facts on :rhs with insert!
but I need to know how to fetch the existing ones in the next chain of rules.
I tried binding the defrecord to variable as in the documentation of clara, in defrule
. But unable to do so with similar constraints as in defrule
(?td <- Temperature
) where Temperature is a defrecord in current session. I tried referring the defrecord as clara.rules.testfacts.Temperature
and clara.rules.testfacts.Temperature.
but it didn't work.
That is where Im not able to find the full structure of writing the defrule externally.
UPDATE This is how I used it actually.
(defrecord User [user-id user-name])
(defrecord UserCriteria [#^ints ids])
(defn fetch-rules-from-file []
(edn/read-string (str "[" (slurp "rules.edn") "]")))
(defn run-rules []
(let [res (-> (mk-session (fetch-rules-from-file))
(insert (->User [:userfact1 :userfact2] )
(->UserCriteria (list nil)))
(fire-rules))])
)
rules.edn file
{
:name "criteria-1",
:lhs [{
:type rules.rules.Users,
:constraints [conditions]}
]
:rhs [(clara.rules/insert! (rules.rules.UserCriteria. [1])]
}
The above mentioned rules works, as it is doing the basic insertion with static data, but what I want to do is get the previous UserCriteria defrecord in the session and update the list.
{
:name "criteria-1",
:lhs [{
:type rules.rules.Users,
:constraints [conditions]}
]
:rhs [(let [id (some-function-call)
updated-criteria (conj (:id rules.rules.Segments.) id)]
(clara.rules/insert!
(rules.rules.UserCriteria. updated-criteria))]
}
Also, I want to know how do we get the fact inserted into the session. Im able to get the defrecord from session using:fact->explanations
key but its a map that is nested into levels of list.
(first (first (:fact->explanation session-data))
This is how the session data looks like:
{:fact->explanations {#rules.rules.UserCriteria{:id [1]} [:rule {fact }]} }
This is giving me the result though but would like to know if there is any better approach.
Upvotes: 0
Views: 124
Reputation: 1
Found a way to figure out the structure of the defrule. You can write a defrule
first and use clojure.pprint/pprint
to get the structure for whichever working defrule you want to write in its meta form to a edn file.
(defrule rule1
"Rule for Active User"
[User (= is-active true)]
[?u <- User]
=>
(println "Active User"))
(clojure.pprint/pprint rule1)
This would print the following:
{:ns-name rules.rules,
:lhs [{:type rules.rules.Users,
:constraints [= is-active true],
}
{:type rules.rules.Users,
:constraints []
:fact-binding :?u
}],
:rhs (do (println "Active User")),
:name "rules.rules/rule1",
:doc "Rule for Active User"
}
Upvotes: 0