UR::Co...ricator(3pm)

πŸ“¦
version 0.470 Β· 2 versions
, in debian bookworm, ubuntu jammy, ubuntu noble

πŸ¦‹ UR::Context::ObjectFabricator πŸ¦‹

okay bestie, so this is UR::Context::ObjectFabricator from the perl docs (section 3pm, user contributed, we love her) β€” and no cap, she's a backstage queen. Let's get into it πŸ’…


✨ NAME ✨

UR::Context::ObjectFabricator β€” tracks the closures used to fabricate objects from data sources 🧡✨


🌸 DESCRIPTION 🌸

So. Object Fabricators are these closures that:

  • take in listrefs of data that come back from data source iterators
  • slice out the bits they need from those listrefs
  • construct UR objects out of the results πŸŽ€

And that's not even all she does β€” she also handles updating the query cache and merging changed DB data with previously cached objects. Multi-tasking icon behavior, honestly πŸ‘‘

lowkey important: UR::Context::ObjectFabricator objects are used internally by UR::Context, and are not intended to be used directly. She's a private queen, iykyk πŸ™ˆ

πŸ’– METHODS πŸ’–

🧚 create_for_loading_template

my $fab = UR::Context::ObjectFabricator->create_for_loading_template(
              $context, $loading_tmpl_hashref, $template_data,
              $rule, $rule_template, $values, $dsx);

Returns an object fabricator instance that can construct objects of the rule's target class from rows of data returned by data source iterators. Object fabricators are part of the object loading process, and they get called by UR::Context::get_objects_for_class_and_rule() to turn a row of data from a data source iterator into a UR object. ✨

So here's the lore πŸ“: for every class involved in a get request, the system prepares a loading template that describes which columns of the data source data get used to construct an instance of that class. For example β€” say you do a get() on a child class, and the parent and child classes store their data in separate tables linked by a relation-property/foreign-key. Then the query against the data source will involve a SQL join (for RDBMS data sources, obviously), and that join produces a result set with data from both tables. messy but iconic πŸ’…

$loading_tmpl_hashref holds the info about which columns of that result set map to which properties of each involved class. The heart of the fabricator closure is a list slice extracting the data for that class, and assigning it to a hash slice of properties to fill in the initial object data for its class. The rest of the closure is just bookkeeping β€” keeping the object cache ($UR::Context::all_objects_loaded) and the query cache ($UR::Context::all_params_loaded) consistent. 🌈

Now the vibes get complicated: the interaction of the object fabricator, the query cache, the object cache pruner, and object loading iterators that may or may not have loaded all their data means the object fabricators have to keep a list of changes they plan to make to the query cache instead of applying them directly. When the Underlying Context Loading iterator has loaded the last row from the Data Source Iterator, it calls "finalize()" on the object fabricator to tell it to go ahead and apply its changes β€” essentially treating that data like a transaction. periodt 🫢

πŸŽ€ all_object_fabricators

my @fabs = UR::Context::ObjectFabricator->all_object_fabricators();

Returns a list of all the object fabricators that have not yet been finalized. the unfinished girlies πŸ’€

⭐ fabricate

my $ur_object = $fab->fabricate([columns,from,data,source]);

Given a listref of data pulled from a data source iterator, it slices out the appropriate columns from the list and constructs a single object to return. one row in, one object out, slay ✨

πŸ’œ is_loading_in_progress_for_boolexpr

my $bool = $fab->is_loading_in_progress_for_boolexpr($boolexpr);

Given a UR::BoolExpr instance, it returns true if the given fabricator is prepared to construct objects matching this boolexpr. UR::Context uses this to figure out whether other iterators are still pulling in objects that could match another iterator's boolexpr β€” and if they are, it should therefore not trust that the object cache is complete. πŸ‘€ don't trust it bestie

🌈 finalize

$fab->finalize();

Indicates to the iterator that the caller is done using it for constructing objects β€” probably because the data source has no more data, or because the iterator that was using this fabricator has gone out of scope. bye bestie πŸ¦‹

πŸ“ apply_all_params_loaded

$fab->apply_all_params_loaded();

As the fabricator constructs objects, it buffers changes to all_params_loaded (the Context's query cache) so everything stays consistent if multiple iterators are working concurrently. At the appropriate time, call apply_all_params_loaded() to take those changes and apply them to the current Context's all_params_loaded. πŸ’–


no thoughts, just cache consistency 🧠✨

and that's the whole page, bestie 🫢 this was perl v5.32.1, dated 2022-01-17, and yes she is UR::Context::ObjectFabricator(3pm) β€” go forth and fabricate responsibly πŸ‘‘πŸ’…

πŸ“¦ where this page comes from