UR::Co...ricator(3pm)
π¦ 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::ObjectFabricatorobjects are used internally byUR::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
- debian bookworm: libur-perl 0.470+ds-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu jammy: libur-perl 0.470+ds-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libur-perl 0.470+ds-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms