Clojure: 1.10.0
clojurescript: "1.10.764
shadow-cljs "2.11.7"
re-frame "1.2.0"
I am creating a SPA using re-frame, and everything is working well. However, I recently watched a video on o'Doyle rules engine and I thought it might be fun to try experimenting with this in my re-frame project. It creates a separate "facts table" in its own atom:
(ns cube-test.twizzlers.rules
(:require
[re-frame.core :as re-frame]
[odoyle.rules :as o]))
(def rules
(o/ruleset
{::print-time
[:what
[::time ::total tt]
:then
(println "upate time rule:" tt)]}))
;; create session and add rule
(def ^:dynamic *session
(atom (reduce o/add-rule (o/->session) rules)))
(defn update-time []
(swap! *session
(fn [session]
(-> session
(o/insert ::time ::total 100)
o/fire-rules))))
I then created a button to activate the update:
[:button.user-action {:on-click #(re-frame/dispatch [::twiz.events/update-time])} "update time rule"]
The rule fires and everything works well, however I see a bunch of re-frame warnings on the console suggesting that re-frame is trying to hook and manage the Odoyle atom as one of it's own:
"twizzler.events.update-time: entered" cljs.core.js:168:20
upate time rule: 100 cljs.core.js:168:20
re-frame: no handler registered for effect:
Object { ns: null, name: "alpha-node", fqn: "alpha-node", _hash: 1411603897, "cljs$lang$protocol_mask$partition0$": 2153775105, "cljs$lang$protocol_mask$partition1$": 4096 }
. Ignoring. cljs.core.js:13285:10
re-frame: no handler registered for effect:
Object { ns: null, name: "beta-nodes", fqn: "beta-nodes", _hash: -674152665, "cljs$lang$protocol_mask$partition0$": 2153775105, "cljs$lang$protocol_mask$partition1$": 4096 }
. Ignoring. cljs.core.js:13285:10
re-frame: no handler registered for effect:
Object { ns: null, name: "last-id", fqn: "last-id", _hash: -1231616450, "cljs$lang$protocol_mask$partition0$": 2153775105, "cljs$lang$protocol_mask$partition1$": 4096 }
. Ignoring. cljs.core.js:13285:10
re-frame: no handler registered for effect:
Object { ns: null, name: "rule-name->node-id", fqn: "rule-name->node-id", _hash: -494456865, "cljs$lang$protocol_mask$partition0$": 2153775105, "cljs$lang$protocol_mask$partition1$": 4096 }
. Ignoring. cljs.core.js:13285:10
re-frame: no handler registered for effect:
Object { ns: null, name: "node-id->rule-name", fqn: "node-id->rule-name", _hash: 1615893599, "cljs$lang$protocol_mask$partition0$": 2153775105, "cljs$lang$protocol_mask$partition1$": 4096 }
. Ignoring. cljs.core.js:13285:10
re-frame: no handler registered for effect:
Object { ns: null, name: "id-attr-nodes", fqn: "id-attr-nodes", _hash: -1814751183, "cljs$lang$protocol_mask$partition0$": 2153775105, "cljs$lang$protocol_mask$partition1$": 4096 }
. Ignoring. cljs.core.js:13285:10
re-frame: no handler registered for effect:
Object { ns: null, name: "then-queue", fqn: "then-queue", _hash: 899186975, "cljs$lang$protocol_mask$partition0$": 2153775105, "cljs$lang$protocol_mask$partition1$": 4096 }
. Ignoring. cljs.core.js:13285:10
re-frame: no handler registered for effect:
Object { ns: null, name: "then-finally-queue", fqn: "then-finally-queue", _hash: 2088468149, "cljs$lang$protocol_mask$partition0$": 2153775105, "cljs$lang$protocol_mask$partition1$": 4096 }
. Ignoring. cljs.core.js:13285:10
"then-finally-queue" and "alpha-node" et. al are presumably o'doyle life cycle events on it's atom, and it looks like re-frame is trying to find handlers for them.
This question isn't really about making odoyle rule engine and re-frame work together, although if anyone has opinions about the plausibility of this scenario I'd be interested in hearing them (yes, there's an overlap between the frameworks, but I would regard the odoyle "fact table" as simply an alternate view that I would manage with re-frame subscriptions).
Anyhow, to make it clearer that this question isn't simply about odoyle, or an effect of odoyle's design, I created a generic atom like so:
(def ^:dynamic *a* (atom 10))
(defn update-atom []
(swap! *a* inc))
and when I drive it, it generates:
"twizzler.events.update-dmy-atom: entered" cljs.core.js:168:20
Uncaught Error: No protocol method IMap.-dissoc defined for type number: 12
cljs$core$missing_protocol https://localhost:8281/js/compiled/cljs-runtime/cljs.core.js:312
cljs$core$IMap$_dissoc$dyn_41386 https://localhost:8281/js/compiled/cljs-runtime/cljs.core.js:2213
cljs$core$_dissoc https://localhost:8281/js/compiled/cljs-runtime/cljs.core.js:2224
cljs$core$IFn$_invoke$arity$2 https://localhost:8281/js/compiled/cljs-runtime/cljs.core.js:6832
re_frame$fx$do_fx_after https://localhost:8281/js/compiled/cljs-runtime/re_frame.fx.js:40
re_frame$interceptor$invoke_interceptor_fn https://localhost:8281/js/compiled/cljs-runtime/re_frame.interceptor.js:216
re_frame$interceptor$invoke_interceptors https://localhost:8281/js/compiled/cljs-runtime/re_frame.interceptor.js:255
re_frame$interceptor$execute https://localhost:8281/js/compiled/cljs-runtime/re_frame.interceptor.js:365
re_frame$events$handle https://localhost:8281/js/compiled/cljs-runtime/re_frame.events.js:85
re_frame$router$IEventQueue$_process_1st_event_in_queue$arity$1 https://localhost:8281/js/compiled/cljs-runtime/re_frame.router.js:580
re_frame$router$IEventQueue$_run_queue$arity$1 https://localhost:8281/js/compiled/cljs-runtime/re_frame.router.js:325
vec__42331 https://localhost:8281/js/compiled/cljs-runtime/re_frame.router.js:417
re_frame$router$IEventQueue$_fsm_trigger$arity$3 https://localhost:8281/js/compiled/cljs-runtime/re_frame.router.js:459
G__42328 https://localhost:8281/js/compiled/cljs-runtime/re_frame.router.js:370
NextJS 3
day8$re_frame_10x$inlined_deps$re_frame$v0v12v0$re_frame$router$IEventQueue$_run_next_tick$arity$1 https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.inlined_deps.re_frame.v0v12v0.re_frame.router.js:372
vec__42751 https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.inlined_deps.re_frame.v0v12v0.re_frame.router.js:478
day8$re_frame_10x$inlined_deps$re_frame$v0v12v0$re_frame$router$IEventQueue$_fsm_trigger$arity$3 https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.inlined_deps.re_frame.v0v12v0.re_frame.router.js:549
day8$re_frame_10x$inlined_deps$re_frame$v0v12v0$re_frame$router$IEventQueue$push$arity$2 https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.inlined_deps.re_frame.v0v12v0.re_frame.router.js:363
day8$re_frame_10x$inlined_deps$re_frame$v0v12v0$re_frame$router$dispatch https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.inlined_deps.re_frame.v0v12v0.re_frame.router.js:699
day8$re_frame_10x$db$init_db https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.db.js:24
day8$re_frame_10x$init_db_BANG_ https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.js:352
<anonymous> https://localhost:8281/js/compiled/cljs-runtime/day8.re_frame_10x.preload.js:3
globalEval https://localhost:8281/js/compiled/app.js:597
evalLoad https://localhost:8281/js/compiled/app.js:1690
<anonymous> https://localhost:8281/js/compiled/app.js:2162
app.js line 597 > eval:312:9
IOTW, re-frame is trying to "manage" this atom as well.
It looks like re-frame hooks all atom processing functions not just its own app-db ratom?
Is there a way I can mark an atom to exclude it from re-frame's hooks? Or will I be forced to create a non-re-frame project to experiment with odoyle? Note: odoyle has an adapter for Rum, so it can work with other reactive frameworks.
Regarding the superfluous messages:
This is an "answer" from the original poster. Since I received no responses, I'll just explain what I discovered and how I dealt with the situation. I do not claim to have any expert knowledge of re-frame beyond what I know as a basic user of the framework.
In looking at the source code for re-frame (which is amazingly quite small, and not very complicated BTW), fx.cljs seems to be the source of all the messages I see. I can see that in fact it has a lot of interceptors:
(def do-fx
(->interceptor
:id :do-fx
:after (fn do-fx-after
After thinking about it, it makes sense that the hooking and intercepting is tied to the code and not to the atom i.e. you typically have one copy of the code loaded to deal with n atoms.
My main concerns about re-frame hooking my non-reframe atoms are twofold: performance and interference. As far as performance goes, this is just re-frame doing a simple check for a handler, not finding it, and printing a warning message. Since state changes are at app level and not on the animation tick (my project is a Babylon.js 3d app), this is not a big issue. Indeed, to add a lookup table of what atoms to monitor or not, while also not a big performance hit, would, if anything, decrease the performance even further. So no big deal to have these messages.
I also realize that re-frame should not be interfering with the non-reframe atom at all. Indeed, these messages are an indication that re-frame is unable to intercept the native atom. So once again nothing to worry about.
So I was able to convince myself that these messages are really nothing to worry about. However, the specter of having a lot of superfluous wordy message clogging up my console was annoying.
To deal with getting rid of all the messages, I made a call to re-frame's set-loggers! call, where I used a regex to filter the superfluous messages, something like:
(defn rf-odoyle-warn-override-logger [& args]
(let [text (apply str args)]
; (prn "utils.rf-odoyle-warn-override-logger: text=" text)
(if (re-matches #".*no handler registered for effect:.*Ignoring.*" text)
(js/console.log "probable rf-odoyle interceptor no handler msg warning detected")
(js/console.warn text))))
Invoked like this in my startup:
(re-frame.core/set-loggers! {:warn utils/rf-odoyle-warn-override-logger})
Now, I just get one simple "collapsed" message in the console:
probable rf-odoyle interceptor no handler msg warning detected
On using re-frame and o'doyle together:
vis a vis the viability of using o'doyle rules in re-frame, I see great promise for me since my main "view" is a babylon.js scene and not the DOM. Thus I need to do a lot of game level logic outside of the DOM, where I think O-doyle will complement re-frame. If your app is a basic Web app where the DOM is your main view, then I think it might feel kind of redundant to attempt to maintain odoyle state on top of the re-frame state (e.g. in app.db).
I opened a Clojure project in Intelij IDEA and everything had been working well until I have made new Clojure workspace and have written some Clojure code in it. When I try to execute this piece of code in REPL I get always the same error. Whatever I write, I get the same error. For example when I try to execute (+ 1 1_ I get the following error:
Syntax error compiling at (test.clj:4:1).
Unable to resolve symbol: + in this context
Has someone already faced this issue?
Here is my project.clj
(defproject test-app "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:dependencies [[cheshire "5.8.1"]
[clojure.java-time "0.3.2"]
[cprop "0.1.13"]
[funcool/struct "1.3.0"]
[luminus-immutant "0.2.5"]
[luminus-transit "0.1.1"]
[luminus/ring-ttl-session "0.3.2"]
[markdown-clj "1.0.7"]
[metosin/muuntaja "0.6.4"]
[metosin/reitit "0.3.1"]
[metosin/ring-http-response "0.9.1"]
[mount "0.1.16"]
[nrepl "0.6.0"]
[org.clojure/clojure "1.10.0"]
[org.clojure/tools.cli "0.4.2"]
[org.clojure/tools.logging "0.4.1"]
[org.webjars.npm/bulma "0.7.4"]
[org.webjars.npm/material-icons "0.3.0"]
[org.webjars/webjars-locator "0.36"]
[org.webjars/webjars-locator-jboss-vfs "0.1.0"]
[ring-webjars "0.2.0"]
[ring/ring-core "1.7.1"]
[ring/ring-defaults "0.3.2"]
[selmer "1.12.12"]]
:min-lein-version "2.0.0"
:source-paths ["src/clj"]
:test-paths ["test/clj"]
:resource-paths ["resources"]
:target-path "target/%s/"
:main ^:skip-aot test-app.core
:plugins [[lein-immutant "2.1.0"]]
:profiles
{:uberjar {:omit-source true
:aot :all
:uberjar-name "test-app.jar"
:source-paths ["env/prod/clj"]
:resource-paths ["env/prod/resources"]}
:dev [:project/dev :profiles/dev]
:test [:project/dev :project/test :profiles/test]
:project/dev {:jvm-opts ["-Dconf=dev-config.edn"]
:dependencies [[expound "0.7.2"]
[pjstadig/humane-test-output "0.9.0"]
[prone "1.6.1"]
[ring/ring-devel "1.7.1"]
[ring/ring-mock "0.3.2"]]
:plugins [[com.jakemccrary/lein-test-refresh "0.24.1"]]
:source-paths ["env/dev/clj"]
:resource-paths ["env/dev/resources"]
:repl-options {:init-ns user}
:injections [(require 'pjstadig.humane-test-output)
(pjstadig.humane-test-output/activate!)]}
:project/test {:jvm-opts ["-Dconf=test-config.edn"]
:resource-paths ["env/test/resources"]}
:profiles/dev {}
:profiles/test {}})
Everything works fine when I write code in my namespace test-app.routes.home, but when I make new Clojure namespace test.clj in the same routes folder, I cant evaluate code in REPL. When I press ctrl+Enter I get this error:
Syntax error compiling at (test.clj:4:1).
Unable to resolve symbol: + in this context
(Maybe) You need to evaluate your namespace (ns ....) before trying to evaluate any other expression.
I want to attach an image with my chat application. I have done with text chat but I am not able to send an attachment with actioncable.
App.global_chat = App.cable.subscriptions.create {
channel: "ChatRoomsChannel"
chat_room_id: messages.data('chat-room-id')
},
connected: ->
# Called when the subscription is ready for use on the server
disconnected: ->
# Called when the subscription has been terminated by the server
received: (data) ->
messages.append data['message']
messages.append data['attachment']
messages_to_bottom()
send_message: (message, chat_room_id, attachment) ->
#perform 'send_message', message: message, chat_room_id: chat_room_id, attachment: attachment
$('#new_message').submit (e) ->
$this = $(this)
textarea = $this.find('#message_body')
attachment = $this.find('#message_attachment')
if $.trim(textarea.val()).length > 1
App.global_chat.send_message textarea.val(), messages.data('chat-room-id'), attachment[0].files[0]
textarea.val('')
attachment.val('')
e.preventDefault()
return false
I cannot comment but I can give you a tips to accomplish it .
As you know rails form_for don't support the ajax upload and it is very hard in rails for ajax upload i had to dig in too deep.
First Install this gem
gem 'remotipart', '~> 1.2'
After adding the gem you can create a form with file input . The best thing is after adding a gem the file get upload automatically.
Be Sure to add remote: true at form_for while creating forms.
I have tried with paperclip gem and it is working perfectly fine . If you problem then ping us
Please bear with this contrived example but it was the simplest thing I could think of to recreate the issue.
(ns something.core)
(defn call-foo [something & args]
(let [a-foo (:foo (eval (:quux something)))]
(apply a-foo args)))
(def Something {
:foo (fn [& args] args)
:bar (fn [something] (call-foo something))
})
(defn make-something []
{:quux 'Something})
Running the following in the REPL or with lein run works well.
(let [subject (make-something)
actual (call-foo subject "hello" "greetings")]
(println actual))
;;=> (hello greetings)
The problem occurs only during this test and executing lein test:
(ns something.core-test
(:require [clojure.test :refer :all]
[something.core :refer :all]))
(deftest a-test
(let [subject (make-something)
actual (call-foo subject "hello" "greetings")]
(is (= ["hello" "greetings"] actual))))
This throws an error. An example output:
ERROR in (a-test) (Compiler.java:6464)
Uncaught exception, not in assertion.
expected: nil
actual: clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to resolve symbol: Something in this context, compiling:(/private/var/folders/0n/c7q7860j34xfc2r1x4q51jrh0000gn/T/form-init9215140948330409114.clj:1:6436)
The line "Unable to resolve symbol: Something in this context" makes me think Something is not in context for some reason while I eval in call-foo. But why is this the case only in the test?
The problem is that eval does not see context. Your 'Something resolves in something.core and something.core-test since you have refered all. It won't resolve from whatever namespace where lein test runs its tests.
To fix the immediate problem change
'Something
to
`Something
so that it is namespace-qualified. The test will then run (and fail), but that's another issue (println returns nil for one thing).
I downloaded AWS SDK and stored it in the same directory of this file, but every tyme this simple script gives this error:
"Fatal error: Undefined class constant 'ACL_PUBLIC_READ'"
This script is for uploading a simple png image on s3:
require 'aws.phar';
$bucket='example';
use Aws\S3\S3Client;
use Aws\Common\Enum\Region;
$client = S3Client::factory(array(
'key' => 'mykey',
'secret' => 'mysecretkey'
));
$client->putObject($_FILES['myfile']['tmp_name'], $bucket , 'file.png', S3Client::ACL_PUBLIC_READ);
How can I solve it?
That constant doesn't exist in SDK 2.x. I think you're looking for this:
http://docs.aws.amazon.com/aws-sdk-php-2/latest/class-Aws.S3.Enum.CannedAcl.html