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

Discussion: Accessing Masked Data #11

Closed
pvande opened this issue May 10, 2011 · 19 comments
Closed

Discussion: Accessing Masked Data #11

pvande opened this issue May 10, 2011 · 19 comments

Comments

@pvande
Copy link
Contributor

pvande commented May 10, 2011

Forked from this comment: #10 (comment)

Data Sample:

name: 'Hello World'
users:
  - name: 'Bill'
    pets:
      - name: 'Yoda'
      - type: 'Cat'
  - name: 'Steve'
    pets:
      - name: 'Wayne'
      - type: 'Llama'

@janl I, like you, am still on the fence about the ../ notation.

Generally, there are a few ways to conceive of a solution:

  • Explicit address (ala handlebars.js), which provides access to literally everything on the stack, but necessarily exposes the implementation of the stack immediately to users. (e.g. are inverted section values put on the stack?)
  • Dot notation with a root anchor, sort of the inverse of handlebars' addressing, would permit you to do fully manual stack traversals (e.g. {{ @.name }} would always resolve to 'Hello World', regardless of stack depth). The downsides to this approach are again exposing the underlying implementation, and eschewing the power of the context stack entirely.
  • Reverse traversals could again solve this particular problem, but fails to solve the more general problem of providing access to any/all masked keys.
  • Skips would allow you to inform the stack traversal to bypass one or more results, which nicely solves the problem of accessing any masked value, but introduces a new syntactic construct that has the potential for abuse. The most attractive feature of this solution is the fact that stil relies on the underlying stack traversal code; this is strictly advice passed to that routine. (e.g. {{ name' }}: not the topmost occurrence of name, but the second; {{ name'' }}: the third occurrence of name)

Of these options, I'm most inclined to support the idea of "skips" at this point.

@groue
Copy link

groue commented May 11, 2011

Hi pvande. I miss something: what is the difference between handlebar's ../name and the name' skip?

@groue
Copy link

groue commented May 11, 2011

Maybe that handlebar's paths are anchored, and that ../name refers to parent's name and nothing else, when name' refers to any name somewhere in the stack, starting at parent?

@pvande
Copy link
Contributor Author

pvande commented May 11, 2011

Stack:
[ { name: 'A' }, { useless: true }, { name: 'B' }, { useless: true }, { name: 'C' }, { top: true } ]

From Handlebars' documentation:

The ../ path segment references the parent template scope, not one level up in the context.
This is because block helpers can invoke a block with any context, so the notion of "one
level up" isn't particularly meaningful except as a reference to the parent template scope.

As I interpret this (read: probably wrong), this would basically translate into {{name}} resolving only against [what Mustache would call] the top-of-stack (e.g. undefined) [in certain cases?], with {{../name}} referring to the context element immediately below the top-of-stack (e.g. 'C').

In Mustache, a lookup for {{name}} is intended to mean "the value of the name key found closest to the top-of-stack" (e.g. 'C'). Presently, Mustache has no way of accessing either of the other two name values. "Skips" would pass over the first result they found, behaving thusly:

{{ name }}     {{! yields 'C' }}
{{ name' }}    {{! skips 'C', yields 'B' }}
{{ name'' }}   {{! skips 'C', skips 'B', yields 'A' }}
{{ name''' }}  {{! skips 'C', skips 'B', skips 'A', yields nil }}

@groue
Copy link

groue commented May 11, 2011

In Mustache, a lookup for {{name}} is intended to mean "the value of the name key found closest to the top-of-stack"

Totally clear, agreed, and let's take it for granted.

And I think the "skip" concept is closest to this natural mustache behavior: +1

BTW: don't you think there is a need for a different but related discussion about the need for anchored lookups?

I mean, If {{#a}}{{b}}{{/a}} is not equivalent to {{a.b}}, because in the latter, b is looked into the found a, and not in the stack, and that there is a consensus on the need for such anchored lookups, then it is natural to wonder how one would make an anchored lookup in the current context, or in the parent context. Actually, handlebar's solution to this is elegant : ../name and ./name are natural expressions for an anchored lookup in the parent and in the current context.

I don't want to add confusion, but both topics (masked data and anchored lookups) are close enough so that we shouldn't consider one without consider the other in the same time.

@groue
Copy link

groue commented May 11, 2011

Ha, anchored lookups are discussed at #10 :-)

@defunkt
Copy link
Member

defunkt commented May 11, 2011

As there's no simple obvious solution, I really think the fix is "Sorry :("

Each proposal adds an entire layer of complexity to Mustache itself that isn't needed, it's just nice. I don't think the complexity is worth the niceness.

For example you could always rename <h1>{{title}}</h1> to <h1>{{page_title}}</h1>.

Naming things is always an issue, in every programming environment: http://laughingmeme.org/2005/12/23/there-are-only-two-hard-things-in-computer-science-cache-invalidation-and-naming-things/

@groue
Copy link

groue commented May 11, 2011

defunkt: you forgot the case of recursive partials.

@pvande
Copy link
Contributor Author

pvande commented May 11, 2011

@defunkt I agree that in most (all?) cases, these proposals are not strict requirements of the language. They are, however, reasonably common cases which trap a number of users. At this point, I would not support any of the mentioned approaches except "skips", because they either a) fail the Mustache-like test or b) add unreasonable complexity. With this comes an implicit claim that "skips" can be supported with minimal complexity: in support of this, I've built a functional prototype for the asserted behavior on top of Milk (diff).

As a proposal, its only purpose is to demonstrate one mechanism that would permit non-local access. I'd like to continue the conversation about how else we could provide non-local access, and whether such a feature is a good idea.

@defunkt
Copy link
Member

defunkt commented May 12, 2011

@groue All I care about are real world examples.

@defunkt
Copy link
Member

defunkt commented May 12, 2011

@pvande I don't agree that these are "reasonably common cases".

Either way, if anything, this kind of complication should be exposed to Views at the API layer. Not in the template syntax. We should strive to add as little as possible to the template. That's the whole point.

@pvande
Copy link
Contributor Author

pvande commented May 12, 2011

@defunkt I may have been mistaken about how common an issue this is. I seem to recall hearing questions raised, and I know this is something that has niggled at me while working on the parser side of things, but I may be guilty of sitting too close to the code.

Let's table this until we have a concrete need.

@defunkt
Copy link
Member

defunkt commented May 14, 2011

I think this (and all spec discussions) would be improved about 100 fold with some real world examples.

@aughey
Copy link

aughey commented Jul 9, 2011

I have a real-world example:

https://gist.github.com/1073313

The problem area is the nested data needs to get access to the _id field of the parent for the onClick javascript code. My only solution here is to write the id field into the dom and walk up the dom if the checkbox is clicked, but that's not an elegant solution.

@pvande
Copy link
Contributor Author

pvande commented Jul 10, 2011

@aughey If in your example you replace the ../_id with the appropriate name of _id, the lookup is correctly handled by any spec-compliant Mustache implementation. This can be verified here.

The issue being discussed here is that if the hashed named by data contained an _id key (as shown here), there would be no way to access the value you were interested in.

@groue
Copy link

groue commented Jul 10, 2011

@pvande: imagine the input element had an id, too. This would still be a reasonable real-world-looking example, with two needs for two differents ids at the same level.

@groue
Copy link

groue commented Oct 30, 2012

GRMustache 6 has introduced "protected contexts". Protected contexts address different yet related problem. They prevent untrusted templates and untrusted data to shadow important keys.

Check https://github.com/groue/GRMustache/blob/master/Guides/protected_contexts.md for a rationale.

@ddw338

This comment was marked as off-topic.

@Cris297esco
Copy link

Bifurcado de este comentario: # 10 (comentario)

Muestra de datos:

name: 'Hello World'
users:
  - name: 'Bill'
    pets:
      - name: 'Yoda'
      - type: 'Cat'
  - name: 'Steve'
    pets:
      - name: 'Wayne'
      - type: 'Llama'

@janlYo, como tú, todavía estoy indeciso sobre la ../notación.

En general, hay algunas formas de concebir una solución:

  • Dirección explícita (ala handlebars.js), que proporciona acceso literalmente a todo lo que hay en la pila, pero necesariamente expone la implementación de la pila de inmediato a los usuarios. (por ejemplo, ¿los valores de la sección invertida se colocan en la pila?)
  • La notación de puntos con un ancla de raíz, algo así como el inverso del direccionamiento del manillar, le permitiría realizar recorridos de pila totalmente manuales (por ejemplo {{ @.name }}, siempre se resolvería en 'Hello World', independientemente de la profundidad de la pila). Las desventajas de este enfoque son nuevamente exponer la implementación subyacente y evitar por completo el poder de la pila de contexto.
  • Los recorridos inversos podrían volver a resolver este problema en particular, pero no logran resolver el problema más general de proporcionar acceso a cualquiera o todas las claves enmascaradas.
  • Skips would allow you to inform the stack traversal to bypass one or more results, which nicely solves the problem of accessing any masked value, but introduces a new syntactic construct that has the potential for abuse. The most attractive feature of this solution is the fact that stil relies on the underlying stack traversal code; this is strictly advice passed to that routine. (e.g. {{ name' }}: not the topmost occurrence of name, but the second; {{ name'' }}: the third occurrence of name)

Of these options, I'm most inclined to support the idea of "skips" at this point.

@jgonggrijp
Copy link
Member

This discussion continues in #154.

@mustache mustache locked and limited conversation to collaborators Nov 10, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants