Coder Social home page Coder Social logo

re-posh's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

re-posh's Issues

When reg-pull-sub use the nested map , how can reactive update the relation data?

I use the :get-tree get nested map tree, when i dispatch update the content, it's will reactive update frontend ui.

(re-posh/reg-pull-sub
  :get-tree
  '[:id :content {:_parid ...}])

but i change the parid , by this code:

(re-posh/reg-event-ds
  :remove-parid
  (fn [_ [_event eid-sub eid-father]]
    [[:db/retract eid-sub :parid eid-father]]))

it's can not reactive update.

Query for attribute :where tuple value always fails

I have a query subscription with a :where clause of [?e :nsm.entity/form [:todo :nsm.entity/todo-1]]. It's being transformed into an erroneous query before being passed to DataScript.

Depending on whether I list the value [:todo :nsm.entity/todo-1] in the :where clause, or whether I input it as a variable, I get two different errors.

A) Including the tuple value directly in the :where clause

(re-posh/reg-sub
 :todos
 (fn [_ _]
   {:type :query
    :query '[:find ?e
             :in $
             :where
             [?e :nsm.entity/form [:todo :nsm.entity/todo-1]]]}))

Uncaught Error: ?e is not ISeqable
    at Object.cljs$core$seq [as seq] (core.cljs:1226)
    at Object.cljs$core$empty_QMARK_ [as empty_QMARK_] (core.cljs:2115)
    at posh$lib$q_analyze$normalize_all_eavs (q_analyze.cljc:78)
    at core.cljs:4719
    at core.cljs:4719
    at Object.sval (core.cljs:3422)
    at Object.cljs$core$ISeqable$_seq$arity$1 (core.cljs:3479)
    at Object.cljs$core$_seq [as _seq] (core.cljs:716)
    at Object.cljs$core$seq [as seq] (core.cljs:1213)
    at Function.cljs$core$IFn$_invoke$arity$3 (core.cljs:2464)

B) Including tuple value as a :variable

(re-posh/reg-sub
 :todos
 (fn [_ _]
   {:type :query
    :query '[:find ?e
             :in $ ?form
             :where
             [?e :nsm.entity/form ?form]]
    :variables [[:todo :nsm.entity/todo-1]]}))

#error {:message 
"Lookup ref attribute … :nsm.entity/todo-1]"
Lookup ref attribute should be marked as :db/unique: [:todo :nsm.entity/todo-1]
, :data {:error :lookup-ref/unique, :entity-id [:todo :nsm.entity/todo-1]}}
datascript$db$entid | @ | db.cljc:833
-- | -- | --
  | (anonymous) | @ | q_analyze.cljc:386
  | (anonymous) | @ | core.cljs:3422
  | (anonymous) | @ | core.cljs:3479
  | cljs$core$_seq | @ | core.cljs:716
  | cljs$core$seq | @ | core.cljs:1213
  | cljs$core$set | @ | core.cljs:9416
  | posh$lib$q_analyze$resolve_any_idents | @ | q_analyze.cljc:385
  • Same error result if I remove :variables from reg-sub & pass it in via (subscribe [:todos [:todo :nsm.entity/todo-1]])

Expected Behavior

The query should produce the entity-ids of entities in the database that match the tuple in the :where [?e :nsm.entity/form [...]] clause.

Notes

  • Above query works if I use the raw DataScript API
(d/q '[:find ?e
           :in $ ?form
           :where
           [?e :nsm.entity/form ?form]]
  (d/db @(get-datascript-db)) [:todo :nsm.entity/todo-1])

#{[3]}
  • The Schema for this attribute in DataScript & Datomic, respectively:
;; This is passed to Datascript (as it only supports subset)
:nsm.entity/form {:db/cardinality :db.cardinality/one}

;; datomic (not used, but here for exposition)
{:db/ident :nsm.entity/form,
  :db/valueType :db.type/tuple,
  :db/tupleTypes [:db.type/keyword :db.type/keyword],
  :db/cardinality :db.cardinality/one,
  :db/doc "Tuple [type,spec] of entity"}
  • In project.clj, I tried [re-posh "0.3.0" :exclusions [datascript]] in order to get newer DataScript 0.18.5 but above errors still occurred

Todo Example does not to work

I tried the example of the commit ad8bf4e. I get some compiler warnings that create-task-panel is not defined. I declared them. Then after running figwheel without warnings, I get the todos app shown but I cannot add one by entering text in the text input.

I added some test code to strike out done tasks when they are check. re-posh handles this as expected.

(defn task-list-item [id]
  (let [task (re-frame/subscribe [:task id])]
    (fn []
      [:div {:class-name "task-list-item"}
       [:input {:type "checkbox"
                :checked (:task/done? @task)
                :on-change #(re-frame/dispatch [:task/set-status (:db/id @task) (not (:task/done? @task))])}]
       [:span (if (:task/done? @task)
                  [:del (:task/title @task)]
                  (:task/title @task))
                  ]])))

another caching bug

  ;; this is bugged. apparently results are cached.
  #_(rp/reg-query-sub
   ::entity-id-by-attribute-value
   '[:find ?e . :in $ ?a ?v :where [?e ?a ?v]])

  (rf/reg-sub
   ::entity-id-by-attribute-value
   (fn [_ [_ attr val]]
     (d/q '[:find ?e . :in $ ?a ?v :where [?e ?a ?v]] @connection attr val)))

First one does not return a different value if entities are retracted and re-added. Latter one does.

Name?

@denistakeda Nicely done!

Just a minor suggestion; While this project is still new, you might want to shop around for other names. R has a core data.frame datastructure, which is quite a different beast, and it might be better not to make it look like you were trying to draw comparisons with it. That being said, it should be rather obvious to most folks familiar with Re-frame/DataScript why you chose the name, and naming things is hard (re-naming them all the more so). So do what you will. But I thought I'd let you know.

How do you handle pull-many?

First of all, thanks for the tool! I'm looking forward using it in a new app but trying to figure out how
to solve some common situations first.

Lets say I need to pull some attributes for a bunch of tasks-ids.
Would be nice to have something like :

(re-posh/reg-sub
 ::task-ids
 (fn [_ _]
   {:type :query
    :query '[:find  [?tid ...]
             :where [?tid :app/type :type/task]]}))

(re-posh/reg-sub
 ::task
 :<- [::task-ids]
 (fn [ids _]
   {:type    :pull-many
    :pattern '[:db/id :task/done? :task/title]
    :ids      id}))

Is there another way to solve this situations with re-posh now?

Thank!

Resetting the db inside the conn doesn't trigger an update

So I've got the database defined as:

(defonce conn (d/create-conn schema))
(connect! conn)

When I reset the conn

(defn reset-conn! [db]
  (reset! conn db))

My subscriptions don't update.

(re-posh/reg-query-sub
  :log/entries
  '[:find  [?log-id ...]
    :where [?log-id :type :log/entry]])

At the moment I'm resetting the conn in a normal event.

(re-frame/reg-event-db
  :reset-system
  (fn [db [_]]
    (let [_ (println (pr-str @db/conn) (pr-str (d/empty-db db/schema)))
           _ (db/reset-conn! (d/empty-db db/schema))
           ]
      {:active-panel :home-panel})))

I've also tried calling

(connect! conn)

Am I missing a step or is this a bug?

Datascript version

[datascript "0.16.6"]

Should Datascript version be updated?
If I have the latest Datascript version in my own project dependency, which version will re-posh use?

Database Swap not triggering repaint of app

I am using re-posh to transact and query my react native data.

I am also trying to implement a restore database feature because I write out my datascript database to a file and I would like to read it back in and swap out the current db with the newly restored database. Here is what I do.

  1. A button is used to trigger the read of the file which then dispatches to the event handler below
(rf/reg-event-db
  :app/restore-db

  (fn [db [_ {:keys [data]}]]
      
      (if (or (nil? data) (empty? data))
        ;; if the restored file is empty - there is nothing to do. Call the normal reframe 
   ;; db setup using re-posh
        (do
          (u/log "--: Restore: No file : creating new :--")
          (rf/dispatch [:reposh-initialize-db])
          )

      ;; otherwise take the string, call datascript/conn-from-db on the read-in string, pass that
  ;; to re-posh's connect function and THAT SHOULD SWAP out the OLD DB for the RESTORED ;;one. 
        (do
           (u/log "--: Restore: calling connect on detransited file :--")
           (re-posh/connect! (in/fromTransitString data))
           (u/log "--: Restore: complete :--")
          )

      )
      app-db
    ))

THis code seems to work beautifully. Except that while I hoped it would cause re-frame triggers to my components that are showing the older data - to now show the data that was in the restored database, .. nothing really happens

The ASK: Do I have to remount my whole application again for the changed database to be 'visible' to the app or is there another function call that I can use in re-posh (or elsewhere) to trigger a repainting of the components whose data has changed

ASK 2: WIth re-posh, do I ever need to explicitly hold on to a reference of the conn that I created initially - for example, by adding a key for it in the reframe app-db ?

THanks

Not seeing retracted datoms

Hi @denistakeda
I am using re-posh and I have noticed that when i look at the datoms in datascript I am not seeing any of my retracted datoms (ie.. for an attribute in an existing entity that has been superceded with a new value) I expected to see at least two or more datoms with the older values.

Symptoms

Here is a log of what I see as I update entity 57's attributes for lastname and email twice

;; logging out datom with id 57 ; look at :user/lastname and :user/email datoms. Txn ids are fine
INFO  ("INTERCEPT datoms 57: "
 (#datascript/Datom [57 :user/addresses 53 536870913 true]
  #datascript/Datom [57 :user/email "[email protected]" 536870916 true]
  #datascript/Datom [57 :user/firstname "Mike" 536870913 true]
  #datascript/Datom [57 :user/lastname "Pasha Wedding" 536870916 true]
  #datascript/Datom [57 :user/owner true 536870913 true]
  #datascript/Datom [57 :user/pin "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4" 536870913 true]
  #datascript/Datom [57 :user/stagename ["DJ Mike Tano" "Mike Tano" "The Mixer"] 536870913 true]))

;;  a little later, I change the email and the lastname .. and you can see that from the txn id
;; but WHERE IS ARE THE OLDER DATOMS FROM ABOVE ? 
;; 

 INFO - ("INTERCEPT datoms 57: "
 (#datascript/Datom [57 :user/addresses 53 536870913 true]
  #datascript/Datom [57 :user/email "[email protected]" 536870918 true]
  #datascript/Datom [57 :user/firstname "Mike" 536870913 true]
  #datascript/Datom [57 :user/lastname "Adenan Wedding" 536870918 true]
  #datascript/Datom [57 :user/owner true 536870913 true]
  #datascript/Datom [57 :user/pin "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4" 536870913 true]
  #datascript/Datom [57 :user/stagename ["DJ Mike Tano" "Mike Tano" "The Mixer"] 536870913 true]))

Problem:

I do not seem to be keeping the historical values of the data I am updating.

Expected behavior:

I expected to see datoms like these as part of the grouping..

 INFO - ("INTERCEPT datoms 57: "
 (#datascript/Datom [57 :user/addresses 53 536870913 true]
   #datascript/Datom [57 :user/email "[email protected]" 536870916 false] <---missing
  #datascript/Datom [57 :user/email "[email protected]" 536870918 true]
  #datascript/Datom [57 :user/firstname "Mike" 536870913 true]
  #datascript/Datom [57 :user/lastname "Pasha Wedding" 536870916 false] <---missing
  #datascript/Datom [57 :user/lastname "Adenan Wedding" 536870918 true]
  #datascript/Datom [57 :user/owner true 536870913 true]
  #datascript/Datom [57 :user/pin "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4" 536870913 true]
  #datascript/Datom [57 :user/stagename ["DJ Mike Tano" "Mike Tano" "The Mixer"] 536870913 true]))


Additional info: I am performing a transact in my event handlers in re-frame precisely as you have indicated:

(rf/reg-event-fx
   :action/handle
 
   [(when ^boolean goog.DEBUG debug) (re-posh/inject-cofx :ds) in/pipeliner in/backup in/postlogger in/ssync in/unifiedNav]

   (fn [cofx [_ {:keys [data]}]]
      (u/log "action/handle -> transacting with ..data: " data)
      ;;transact
      {:transact [data]}

      );;end fn
    ) ;; return datascript transaction

and here is a log message of what this handler receives for each case

("action/handle -> transacting with ..data: "
 {:db/id 57,
  :user/addresses [{:db/id 53}],
  :user/email "[email protected]",
  :user/firstname "Mike",
  :user/lastname "Pasha Wedding",
  :user/owner true,
  :user/pin
  "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4",
  :user/stagename ["DJ Mike Tano" "Mike Tano" "The Mixer"]})

and

("action/handle -> transacting with ..data: "
 {:db/id 57,
  :user/addresses [{:db/id 53}],
  :user/email "[email protected]",
  :user/firstname "Mike",
  :user/lastname "Adenan Wedding",
  :user/owner true,
  :user/pin
  "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4",
  :user/stagename ["DJ Mike Tano" "Mike Tano" "The Mixer"]})

What am I doing wrong ? if anything at all..

thanks

Trouble creating a re-posh/datascript DB via an AJAX call

Hi @denistakeda,

Thank you for your excellent library. I've enjoyed playing with it and I have been trying to make an app where I allow users to upload a file which I parse server-side, create a datascript DB, and then send the full DB back to the browser where I can write components against the DB that allow for data exploration.

However, I am running into issues connecting the AJAX call to re-posh. While it seems that my issue is probably due to incorrectly parsing the returned db (and therefore with how I am handling the AJAX call with transit), I think this issue may be relevant to other potential users of this library so I'd like to post it here. If you can help me solve this issue, I would be happy to document the use case as an example in the repo.

Here is the relevant code and the error messages.

;; client code
;; In this case I am not POSTing/uploading the file
;; I am simply using a GET call to try to pull a datascript DB from the server
(rp/reg-event-ds
  :upload
  (fn [db [_ ds]]
    (GET
      "/upload"
      :format :transit
      :response-format :transit
      :handler #(re-frame/dispatch  [:create-new-db  %1])
      :error-handler #(js/alert (str "Didn't Work !" " Response:" ds)))
    ds))    ;; pure handlers must return a db (unchanged in this case)

;; create the new ds
(rp/reg-event-ds
  :create-new-db
  (fn  [_ [_  ds]]
    (print-str ds)
    (dt/read-transit-str ds)))

;; server code
;; the upload currently serves and existing datascript db (no upload/parsing is done here)
(defroutes home-routes
  (GET "/" []
       (home-page))
  (GET "/upload" []
    (-> (response/ok genbank/ds1) ;; am I wrapping the ring/transit response incorrectly here?
        (response/header "Content-Type" "application/transit+json"))))

This image shows the datascript DB is being fetched:

screen shot 2017-12-29 at 2 20 31 pm

However, I am running into issues parsing the JSON:
screen shot 2017-12-29 at 2 22 16 pm

So it seems I am having trouble reading and returning the Datascript DB from the server but have been getting nowhere with my normal approach of fiddling about until things work - in other words, I am clearly missing something. I would appreciate any pointers you might be able to provide.

Thanks,
zach cp

Feature Request : Datalog Rules

So I'd like to be able to use datalog rules in re-posh, but i'm not sure it is actually possible.
Some ideas :

  • having a (reg-query-sub key query rules) version of (reg-query-sub key query)
  • having a {:type :query :query q :variables [...] :rules [...]} format for reg-sub

I may do a PR about that if you're okay with this.

Don't see updates of a datom which properties are edited

i use figwheel during development. naturally i make a lot of changes and every time figwheel reloads the page. when i use reframes's reg-sub it works fine, but when i switched to re-posh's reg-query-sub it seizes to update the subscription after figwheel refreshes the page. i wonder what did i do wrong?

my initial db:

(def initial-db
	[{:db/id     1
	  :app/route [:root]}])

my handler:

(rp/reg-event-ds
	::route
	(fn [db args]
		[[:db/add 1
		  :app/route (rest args)]]))

and a subscription:

(rp/reg-query-sub
	::route
	'[:find ?route .
	  :where [1 :app/route ?route]])

License mismatch

LICENSE file indicates the ECLIPSE PUBLIC LICENSE but README indicates the MIT license

Wording clarification

Hello,
Thanks for this awesome project, I'm quite thrilled to refactor the code of a pet project so I can use it. However, would you mind some clarification? The readme states

re-posh is a ClojureScript library

but all the code is in cljc files. Do you see any reason it could smoothly work, or not work, on a clj runtime? As far as I know, you use datascript which is also written in cljc files so it should work but I'd like to know the viewpoint of the maintainer.

Thanks in advance!

is missing? supported

Hi, I have a subscription that uses missing? to check if an attr is set.
This query works fine when directly executed by datascript, but re-posh does not respond reactively when the query output is changed.

(rp/reg-query-sub
 :mysub
 '[:find [?k ...]
   :in $ ?vf
   :where
   [?vf :some-attr ?k]
   [(missing? $ ?k :attr)]])

unquote does not work in reg-query-sub quote

Suppose I have the following function to keep track of my singleton database IDs:

(def kwd->id
  (let [ids (atom {})]
    (fn [kwd]
      (kwd (swap! ids #(assoc %1 kwd (get %1 kwd (int (gensym "")))))))))

And this initial DB state:

(def ^:private initial-db-state
  [{;; :db/ident :timerange ;; cannot use :db/ident yet due to: https://github.com/denistakeda/re-posh/issues/41
    :id (kwd->id :timerange)
    :timerange/timerange {:timerange "24h"}}])

Then the following query does not yield the correct result and instead gives the error "Tuple binding cannot be empty":

(rp/reg-query-sub
   ::timerange
   (let [id (kwd->id :timerange)]
     `[:find ?t . :where [~id :timerange/timerange ?t]]))

I also tried inlining the ID retrieval:

(rp/reg-query-sub
   ::timerange
   `[:find ?t . :where [~(kwd->id :timerange) :timerange/timerange ?t]])

Support combined pull and query in a subscription

It would be really handy to be able to combine a pull and query in a subscription like you can in datascript. Assuming you want to retrieve all entity attributes for a particular product containing the unique attribute :inv/sku, it could look something like this:

(re-posh/reg-pull-sub
 :item-by-sku
 (fn [ds [_ sku]]
   (datascript.core/pull '[*] (datascript.core/q '[:find ?e
                                                   :in $ ?sku
                                                   :where
                                                   [?e :inv/sku ?sku]] ds) ds)))

enrich should be defined supporting both ds and db

Here is a suggested implementation:

(defn enrich [f]
  (->interceptor
   :id :rp-enrich
   :after (fn enrich-after [context]
            (let [event (get-coeffect context :event)
                  get-prev #(if (contains? (get-effect context) %1)
                              (get-effect context %1) ;; If no effect is returned, we provide the original coeffect.
                              (get-coeffect context %1))
                  prev-db (get-prev :db)
                  prev-ds (get-prev :ds)
                  new (f {:db prev-db :ds prev-ds} event)]
              (-> context
                  (assoc-effect :ds (or (:ds new) prev-ds))
                  (assoc-effect :db (or (:db new) prev-db)))))))

How to idiomatically get value from the ds in an event handler?

Suppose I have this event handler:

(re-posh/reg-event-fx
   :my-event
   [(re-posh/inject-cofx :ds)] ;; inject coeffect
   (fn [{:keys [ds]} [_ id k v]] ;; ds here is the DataScript database
      {:transact [[:db/add id k v]]}))

In which I inject the ds coeffect. I want to know how to actually get a value out of the datastore. Do you use a datascript query like so:?
(d/q '[:find ?foo . :where [...]])
But this makes the event handler impure because we're using a function (d/q ) that's declared outside the scope of the event handler.
Is there a fix around this?

a reg-event-ds handler is called with nil as value of parameter ds

  1. Situation
    Registering a handler for an event like so:

(reg-event-ds
:save-node
(fn [ds [_]]
(nil? ds) ;; is true
))

calls the handler with ds = nil.

  1. Analysis

2.1 In re-posh.coeffects the datascript db ist stored under the key :conn

(assoc coeffects :conn @@store)))

2.2 In re-posh.events

the datascript db gets destructured to the key :ds

... {:keys [ds]} ...

2.3 There is nothing in coeffects map to key :ds.
2.4 In re-posh.events

(handler ds signal)

gets evaluated with ds = nil

  1. Solution
    3.1 Use the same key in both namespaces re-posh.coeffects and re-posh.events

reg-query-sub registered subscription is not returning latest value

from REPL (after a change in the UI from 24h to 1w):

state.core=> @(rf/subscribe [::timerange])
{:timerange "24h"}
state.core=> (d/q '[:find ?t . :where [:timerange :timerange/timerange ?t]] @connection)
{:timerange "1w"}

sub is defined as:

(rp/reg-query-sub
   ::timerange
   '[:find ?t . :where [:timerange :timerange/timerange ?t]])

and the event which sets the new value is defined as:

(rp/reg-event-ds
   ::set-timerange-from-query-param
   [rf/trim-v]
   (fn-traced [_ [timerange]]
              [[:db/add :timerange :timerange/timerange (timerange/query-string-param->timerange timerange)]]))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.