Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Centralizing to_liquid #1532

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft

Centralizing to_liquid #1532

wants to merge 3 commits into from

Conversation

tjoyal
Copy link
Member

@tjoyal tjoyal commented Mar 3, 2022

WIP

As part of #1205 I am exploring cases of @context missing through rendering.

The following explore:

  • Grouping invocations of object.to_liquid and object.context= as single operation.
  • Ensuring Proc optimizations are shared.
  • Limiting code paths manual management of object before their "conversion" to_liquid.

Still a few TODOs to work through and I need to figure out what goes in this PR vs what can be tackled separately (either before or after).

@@ -861,7 +861,7 @@ def test_all_filters_never_raise_non_liquid_exception
{ foo: "bar" },
[{ "foo" => "bar" }, { "foo" => 123 }, { "foo" => nil }, { "foo" => true }, { "foo" => ["foo", "bar"] }],
{ 1 => "bar" },
["foo", 123, nil, true, false, Drop, ["foo"], { foo: "bar" }],
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think passing a Class here is something simply not supported as it cannot be done in a context that runs outside the standard filters.

Before the current changes, you will see a e.respond_to?(:to_liquid) ? e.to_liquid : e in lib/liquid/standardfilters.rb.

Only the StandardFilters apply that respond_to? and I believe it is the user responsibility to always pass in a "Liquid compatible" object back to the context and not for Liquid to silence the unexpected input.

@@ -582,8 +582,7 @@ def empty?

def each
@input.each do |e|
e.context = @context if e.respond_to?(:context=)
yield(e.respond_to?(:to_liquid) ? e.to_liquid : e)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removal is core to the goal I am trying to reach.

While this one filter is in the main codebase, any filters built by the gem users currently need to be aware of build around this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This e.respond_to?(:to_liquid) check seems clearly broken and seems to_liquid could be done unconditionally without these other changes.

I think at the moment filters should be able to depend on the immediate value being passed in being a liquid value. They just need to use to_liquid conversions for nested values. Even if that weren't the case, we would still have similar concerns in drops, so I don't really see a good way of providing a non-leaking abstraction around this concern at the moment.

Comment on lines +259 to +268
if object.is_a?(Array)
object = object.map do |obj|
contextualize(obj)
end
elsif object.is_a?(Hash)
new_obj = {}
object.map do |k, obj|
new_obj[k] = contextualize(obj)
end
object = new_obj
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a non-trivial conversion to be doing on variable access, especially since there wouldn't be anything to make sure it isn't done redundantly. E.g. if an array of hashes were iterated, then this deep conversion would be done when accessing the array along with the inner hashes, then each hash would be converted again when they are accessed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also completely remove the advantage of Proc lazy evaluation.

I'm not sure how much lazy said evaluation is needed when it comes to non-root elements, but it is an impactful mechanism.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants