Open zrothberg opened 4 years ago
I've been looking at a similar problem recently. Looking at your suggestion, it seems quite specific, I wonder if what you're asking cannot be more generally fixed by:
include
to return a value somehow (challenge is how to specify the name of the return value inside and outside of the include). Maybe a include_with_result
tag could help, which might be pretty much what your mask
tag might be.assign
.IMHO, both of these things could also be independently useful (i.e. you might want to create an object at the top of your template and use it further below, or let an include return a string rather than an object).
Regarding your example:
{{old_object}}
in your mask?new_object
and return_object
as names for the same thing?Oh, just read up on render
and include
tags and it seems the include
tag can already "return" objects, since its scope is shared with the parent scope (so any variables written to are visible in the parent scope). But include
is deprecated for this very reason, so some way for render
to return values in a controlled way would still make sense.
So quick rant and proposal followed by use cases and reasoning. I would like to propose a new feature I am going to refer to as "masks" for liquid objects.
What is a mask? A mask is a object modifier that takes a liquid object and returns a new masked one only using passed values and globals. The idea is to be able to create new attributes/modify existing ones for objects in a consistent, predictable, and repeatable manner. An example of this would be
This would allow us to encapsulate website wide object logic into the objects themselves instead of into externally referenced snippets and render functions. Further this would cut down on the number of local variables in the template and snippet sections as the ones used to calculate values would be moved into the mask scope and could be discarded after calculation. I believe the masks could also be cached with a high hit rate and may help speed up page load if we where to restrict them to global scoped variables only. Most importantly this greatly increase developers flexibility within platforms using liquid. Being able to create new object scopes allows for a wide variety of applications without having to expose to much to external parties.
A few uses cases from our own code base in shopify. Product status, Product compare at price, Collection filter options, Custom Json objects, ect.
Product status and compare at price are values that need to be calculated for each product and are used anytime a product is shown on our site. Being able to ensure the same value we calculate at the homepage is the values we calculate at the collection page would be extremely helpful and creates enforceable consistency.
Now technically we can emulate some of this behavior right now with render but it would require a lot of reworking our snippets to make them load from product view down. As well as force us to either needlessly calculate values, have ugly if else statements to pass caller references to ensure we only calculate what we need to each time, or separate the calculations into different render snippets. Being able to mask our objects would be much more easily transferable to most liquid code as it would simply require you to replace the template and snippet file references. You would not even need to remove old calculations allowing for users to test the feature out in a piecemeal fashion.
Anyway let me know what yall think. I read a fair amount of the codebase here but I do not write in ruby so if I am missing some implementation details that would make this impossible or not very efficient I apologize. Really just looking for feedback and if this is something that seems interesting to do.