Closed sl1m3d closed 12 years ago
Hi @psybert, nice to see you back :-)
This "stealing" behavior is right is the mustache spec. There's no way to escape it. The solution to your issue is simply to have fred have an empty array of friends.
Generally speaking, a way to look at your code as it is could be: "Hey, Fred, do you have any friends? - Dude, I don't know - You don't know? OK, I'll assume anything then". One could say that fred doesn't fulfill the contract on the "friends" key, which is "return an array of friends". As soon as fred returns an empty array, it would become: "Fred, any friend? - Nope - Good for you! Friends are much overrated."
I maintain that fred should return an explicit array, but you deserve a more complete answer.
Do you know that {{foo.bar}}
is different from {{#foo}}{{bar}}{{/foo}}
? The dot has bar
looked right into foo
, and not up the context stack.
This scope-restriction syntax could help here, and you could write: {{#enemies}}...{{#self.friends}}...{{/self.friends}}...{{/enemies}}
Beware, however, that the "self" key is not defined by mustache: this template would work because of the underlying KVC implementation of GRMustache. So this technique is not cross-language, and the template could not be reused in another mustache implementation.
One could wish writing {{#enemies}}...{{#.friends}}...{{/.friends}}...{{/enemies}}
. This is not in the spec, and not supported by GRMustache. It may be a good idea to open an issue in the https://github.com/mustache/spec repo.
Final thought: really have fred return an empty array.
Hmm... Wasn't able to get the {{#self.friends}} syntax to work. Any ideas?
I agree on the data issue, (fred should have an array of no friends) except I don't own the data :(
I really like the {{#.friends}} syntax, as we also thought about it; the . just seemed natural to us yesterday when trying to get it to work.
The {{self.friends}}
stuff doesn't work with NSDictionary… Damned, we're out of luck.
Does the data come from some JSON request?
Yes it comes from JSON
No chance you have the server fix its representation?
I see only two solutions, none of them satisfying:
Now this really deserves an issue in the https://github.com/mustache/spec repo. You can link to this real story.
Yea, it's not my server. We've been using the same data source for about 1.5 years now with another template system for iOS. I don't know if using the delegate to look for "friends" is a good idea considering there's hundreds of templates we use with varying data sets.
What would it take to code support for {{#.friends}},{{#self.friends}} or {{#this.friends}}?
(I'm willing to use a modified version for now)
I'll open an issue with the mustache spec repo too.
The method you need to change in order to support {{#.friends}}
is [GRMustacheTemplateParser invocationWithToken:error:]
.
It may not be easy to update. But your goal is, quite definitely, to have the keys
local variable contain an array of two objects : @"."
and @"friends"
. Now the last line of the method, return [GRMustacheInvocation invocationWithToken:token keys:keys]
will return an invocation which gives what you need.
When you're happy, rebuild GRMustache with make clean && make
in the terminal. This will give you an updated static library.
Ok I created the hack for now. Thanks for all your help. Going to create an issue at the spec page.
for those who want this hack too, add this at line 255 in GRMustacheTemplateParser.m. It's not really bullet proof as I'm sure varying whitespace will blow it up.
if (i == 0 && length > 1) {
[keys addObject:[content substringWithRange:NSMakeRange(identifierStart, i+1-identifierStart)]];
identifierStart = 1;
}
Looks like there's already an issue opened on the spec for this. https://github.com/mustache/spec/issues/10
I've read this issue 10, which doesn't look like it's anywhere close to a resolution of the issue :-(
Oh well :\
I think the . to limit the context makes sense, as clearly a couple other people were thinking the same thing. Perhaps there can be a setting in GRMustache for it (setAllowDotToLimitContext) default to NO. :)
You know what? Bundle your changes in a nice bullet proof pull request, and I'll accept it.
@psybert I'm doing it. GRMustache4 is about to be released.
GRMustache4 is out, with solutions for #18 and #19. Thanks for your contribution, @psybert.
Issue closed :-)
Awesome. Thanks @groue
Now if only we can figure out a clean way to write our own filters and formatters :)
It's actually hard not to fight against Mustache, considering the simplicity of the spec. But this simplicity is also key to its success. My line is to let GRMustache users tweak and hack, without compromising the Mustache spec. Thanks to users like you, most common use cases have an answer now. It has to be ugly sometimes. It used to be much more awful :-)
You know, before I shipped GRMustache, the unavoidable templating system was MGTemplateEngine. It's certainly not a bad beast. Besides, it's much richer, feature-wise. Even if Mustache is trendy, remember that one should always choose the tool that best fits her needs!
@psybert, you wrote: "We've been using the same data source for about 1.5 years now with another template system for iOS." Was it MGTemplateEngine? Another one? I'd be interested in the rationale behind switching to Mustache, if you have a couple of minutes.
sure, what's a good e-mail address i can reach you at?
gr-at-pierlis.com
I've run into a real world scenario that I've been unable to resolve. Here's a sample of what I'm trying to do:
How can I stop mustache from looking up the context stack when inside an array, or how can i set the context for an array? I know that some other implementations use this. to overcome this, but wasn't sure if there was a better way. I wouldn't want to turn it off totally, but be able to do so through the template syntax.
Here's some sample code so you can see what I'm talking about
Result:
So as you can see fred has no friends, but according to the template he does (he's stealing my friends!). Maybe I'm looking at this weird, but we haven't been able to figure out a way to make this work.