velocity-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Boris Partensky <boris.parten...@gmail.com>
Subject Re: upgrading from 1.5 to 1.7 compatibility issues
Date Mon, 30 Apr 2012 18:16:12 GMT
Yep, I am afraid we do set globals from within macros...

On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nbubna@gmail.com> wrote:
> Can you set velocimacro.context.localscope = true or is it important
> for your system to be able to #set global stuff from within macros?
>
> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky
> <boris.partensky@gmail.com> wrote:
>> Thanks Nathan, I think I do get the whole scoping idea, but my
>> understanding was that one of the reasons to turn all scoping off by
>> default (and have those properties to begin with) was to provide
>> backward compatibility - as in: I upgrade to 1.7 and then I start
>> turning on all those nice bells and whistles and use scopes and what
>> not. Not so seems like? I also find somewhat strange that a a formal
>> argument to a macro takes precedence and overwrites a global variable
>> with the same name. How would one go about upgrading existing systems?
>> We have roughly 1900 macros, big chunk of those are nested... Maybe I
>> am misunderstanding something, but this issue makes it almost
>> impossible to upgrade (at least for us).
>>
>>
>> Thanks
>> Boris
>>
>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nbubna@gmail.com> wrote:
>>> Yeah, it was intended, and part of an overall move toward
>>> fixing/simplifying Velocity's variable scoping, avoiding the
>>> complexities and costs (performance, yes, but mostly time/brainpower
>>> for users and devs alike) of more programming language type behavior.
>>> Velocity has long aspired to be a straightfoward template engine and
>>> avoid being a complete scripting language.  (Implicit) variable
>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the
>>> latter; after all, one big fat namespace is always unmanageable,
>>> right?  Well, there's ways to make that easy to manage. :)  Let's call
>>> it "optional, provided, explicit scoping", explicit because you don't
>>> have to grok the contextual scope to understand a reference, optional
>>> because you can ignore it, and provided because Velocity does the work
>>> of choosing "prefixes" and creating/destroying the scopes (as any
>>> implicit scoping system does).  So everything is becoming globally
>>> scoped, but it is now trivial to turn on automatic, explicit scopes or
>>> namespaces that you can use when you don't want things to live in the
>>> global scope.
>>>
>>> Here's an example...  Do you use $velocityCount to get an index of
>>> sorts inside of #foreach directives?  Well, that's an example of mixed
>>> implicit/explicit namespacing that gets messy when you nest
>>> #foreach's, with no good way to get the parent's count and
>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and
>>> so on.  Now, we automatically manage a $foreach var that not only has
>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on
>>> (see http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html).
>>>  It also, of course, accepts any property you want to set on it (like
>>> any map).  This makes templates instantly understandable, making
>>> debugging much better.  You always know exactly what you are referring
>>> to, and so does anyone else reading the template.
>>>
>>> #foreach is the only 'content directive' that has its explicit scope
>>> automatically turned on, but all content containing directives
>>> (including custom body macros) can have their own explicit,
>>> auto-managed scope, named after themselves.  for example, you can flip
>>> the macro scope on:
>>>
>>> macro.provide.scope.control = true
>>>
>>> and do:
>>>
>>> #macro( outer $arg )
>>>  #set( $macro.arg = $arg )
>>>  #inner( 'inner' )
>>> #end
>>> #macro( inner $arg )
>>>  #set( $macro.arg = $arg)
>>>  inner: $macro.arg
>>>  #if( $macro.parent )outer: $macro.parent.arg#end
>>> #end
>>>
>>> #outer( 'outer' )
>>> #inner( 'just inner' )
>>>
>>> and get
>>>
>>>  inner: inner
>>>  outer: outer
>>>  inner: just inner
>>>
>>> Hope this helps...
>>>
>>> In any case, there was plenty of thought and discussion that went into
>>> this change.  Search http://velocity.markmail.org for 'scope' and you
>>> should find more on this.
>>>
>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky
>>> <boris.partensky@gmail.com> wrote:
>>>> Hello, while going through the upgrade I noticed an incompatible
>>>> behavior during nested macro evaluation. Looks like in 1.7 (all
>>>> default properties) child macro has access to variables set in parent
>>>> macro scope (and those take precedence over globals), and 1.5 sees
>>>> globals. In the following example, in 1.5 unit test the following
>>>> template will evaluate to "globalvar", and in 1.7 - to
>>>> "outermacroparam". Is this expected behavior?
>>>>
>>>>
>>>> 1.5 test case
>>>>
>>>>
>>>> public void testVelocityNestedMacroScope() throws Exception
>>>>    {
>>>>        VelocityEngine ve = new VelocityEngine();
>>>>
>>>>        ve.init();
>>>>
>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>                          "#innerMacro('blah')"+
>>>>                          "#end"+
>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>
>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')";
>>>>        StringWriter eval = new StringWriter();
>>>>        boolean b = ve.evaluate(new VelocityContext(), eval, "foo", template);
>>>>        assertEquals(eval.toString(), "globalval", eval.toString());
>>>>
>>>>    }
>>>>
>>>> 1.7 test case
>>>>
>>>>
>>>>  public void testVelocityNestedMacroScope()
>>>>    {
>>>>        String template = "#macro(outerMacro $arg1)"+
>>>>                          "#innerMacro('blah')"+
>>>>                          "#end"+
>>>>                          "#macro(innerMacro $arg2)$arg1#end"+
>>>>
>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')";
>>>>        String eval = evaluate(template);
>>>>        assertEquals(eval, "outermacroparam", eval);
>>>>
>>>>    }
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>>> For additional commands, e-mail: user-help@velocity.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
>> For additional commands, e-mail: user-help@velocity.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Mime
View raw message