Fork me on GitHub
#fulcro
<
2022-03-23
>
sheluchin13:03:20

One more question, for now 🙂 In scenarios where there is a to-many relation between Foo -> Bar -> Baz, how do I structure my RAD attrs/reports to do something like "get the baz/datetime from a specific foo's latest baz"? I understand how to write a set of attrs/resolvers to eventually satisfy a resolver that explicitly outputs foos-latest-baz-datetime, but in doing so, I'm kind of ending up with a bunch of resolvers that seem to do nearly the same thing. Following this approach, I end up with more attrs/resolvers like foos-EARLIEST-baz-x, foos-LATEST-baz-y, and so on. What I'd like to do is just have a foo/baz-set resolver that accepts some parameters for the baz query like {:order-by :datetime :limit 1} and returns something like {::foo/baz-set [{::baz/id 1} ...]}, and then use the auto-generated attribute resolvers from baz to pull whatever fields I need from there, like datetime, x, and y. I can do it with Pathom queries alone, but when trying to arrive at the same solution with RAD reports, I get this explosion of resolvers that seem too specific in their outputs. Any suggestions? Should I stop worrying and just make extra resolvers for each sort/field access combination my reports need, or is there a better way?

Jakub Holý (HolyJak)13:03:16

You can pass parameters to the resolver used by a report, no? I'd use that (and user-invisible report params to hold the current settings)

Jakub Holý (HolyJak)13:03:40

And you my-report-resolver can output a (map with) list of idents where details will be filled in by the ident resolver

sheluchin13:03:44

If the ro/source-attribute is something generic like :all-foos, it just returns a set of foo/id. I then want to get the foos-latest-baz-datetime for each foo, along with foos-earliest-bar-x. So there's a difficulty in that the params passed to the resolver by the report only go to the ro/source-attribute resolver. Is my problem that I'm using generic entity resolvers as my source-attributes instead of pairing a specific report resolver to each report?

Jakub Holý (HolyJak)13:03:59

Yes, I would make a dedicated resolvers. Seems as the simplest solution to me. YMMV

Jakub Holý (HolyJak)13:03:52

You can add pathom pluggin that puts the params into the top of pathom env, used in RAD demo and discussed here in the past weeks. Then nested resolvers can also see them

sheluchin13:03:15

I don't think that would solve it totally for me because there would still be the issue of param name conflicts. Like if I want to sort one relation by desc and another by asc, a simple :order-by [:datetime :desc] would conflict with the :asc counterpart. I guess namespacing the nested resolver's param keys is an option, but that seems like it would lead to more over-specifying. Probably a single report resolver that takes :bar/order-by and :baz/order-by and then passes them on as the generic :order-by keys when calling the ident queries would work?

👍 1
Jakub Holý (HolyJak)13:03:47

Experiment :)

🧫 1
🥼 1
sheluchin13:03:45

Thanks as always @U0522TWDA. I have some ideas for new approaches to try.

🙏 1
sheluchin16:03:01

> And you my-report-resolver can output a (map with) list of idents where details will be filled in by the ident resolver I'm able to get it to work but it doesn't feel right. I have foo-report-resolver return the foo/id and foo/baz-set. In my ro/columns, I use foo/name and baz/datetime. The JVM complains: > EQL query for ::baz/datetime cannot be resolved. Then I assoc:

ro/row-query-inclusion [{::foo/baz-set [::baz/datetime]}]
ro/column-formatters {::baz/datetime (fn [this v {{::baz/keys [datetime]} ::foo/baz-set}]
                                       datetime)})
and it gets the right value in the column, but the JVM complaint is still there. If I add:
ro/load-options {:without #{::baz/datetime}}
The JVM error goes away, but then the query doesn't include ::baz/datetime at any level, so my column formatter no longer works and I no longer have a value in the column. It's not so much that I mind the error, but I'd like to understand how to do this properly. I've looked at the demo repo plenty but I can't quite put it together. Any more advice for how to line up the attrs in ro/columns with related attributes from other models? It feels very close.

tony.kay17:03:50

So, my first question is “how would you do it without RAD or Pathom”?

❤️ 1
tony.kay17:03:44

Crossing relations in a report is not magically solved by any technology…there are too many different things you might want to be doing at a given time. I would suggest that if you were doing that in LAMP, for example, you’d be writing a single endpoint that does some complex crazy SQL thing and then returns it as a big blob. The fact that Pathom lets you pick apart pieces, give them names, and then reassemble them does not solve the problem of “possibilities” (combinatorial complexity in this problem space). Looking for a “universal easy solution” seems pointless from my perspective, since the inherent complexity simply “is”. So, you choice of managing that complexity comes down to your own personal take on your project. My primary concern in this case is: Are those specialized resolvers reusable elsewhere? If the answer is “no”, then lean towards compact and efficient (minimal) resolvers that are specialized to the report, and move on. You might even go as far as making a single resolver that uses pathom final to spit back the entire report content as a “blob” like you would have in LAMP, and avoid the excess resolver overhead.

❤️ 1
sheluchin18:03:39

Without Pathom I'd probably put each entity on a separate REST endpoint and have the client follow the pointers, making as many requests as necessary and avoiding nesting anything but references. My thinking here is that Pathom sort of takes the place of your usual REST client and walks the graph to put the pieces together into what's ultimately required... just as long as you give it the right edges to follow. I think I get your point. While Pathom can be the glue for all of the small/specialized attribute accessors, it doesn't have to be used that way, and in cases where "too much" glue would be necessary and re-usability is not a huge concern, it's can be better to concentrate the work to one place instead of relying on the walks. Okay, so given that, I think I'll try the "one big resolver" approach in a few places. Thank you for the detailed explanation. The power that Pathom gives is pretty awesome.. but I understand what you mean by not trying to use it to break logical limits 😛 Thanks @U0CKQ19AQ!

👍 2
tony.kay18:03:26

The one problem that you may be failing to fully register is that every time you cross a reference then there can be any number of things you might want to do: • Filter • Sort • Aggregate and to make matters worse, these decisions compound for every additional reference you cross. Throw in some polymophism (that edge, say :feed/items, can point to an image or a comment) and you now have a need to parameterize the decisions around the parameters of handing the edge. Bleh

tony.kay18:03:34

So this is why RAD doesn’t really even try to make a stab at handling edges in reports “for you”. The sheer number and complexity of options would be very hard to get right, and just as hard to understand/use.

❤️ 2
sheluchin21:03:19

Thanks for emphasising the explosion of complexity that happens when crossing references. It does help understand why it's not a core part of the library. I guess when it comes to this area it's best to go for pragmatism over idealism in the design. I suppose the final conclusion to my initial question is to - as I initially guessed - stop worrying and just create new resolver/attr pairs whenever crossing references, or use a great big resolver that does all the heavy lifting. I suppose one other option would be to run a periodic task to collect the needed values to a central per-report document... that would keep the report setup more consistent and would offer some performance gains where that's a concern.