Freemarker expected extended hash error - freemarker

I've added an objectwrapper in freemarker that wraps a type of object as a templateHashModel. I don't seem to be able to iterate over it - if I try to iterate as a hash, (ie <#list blah as x,y> I get this:
Expected an extended hash, but this has evaluated to a hash
(au.com.amp.common.json.JObjMap wrapped into au.com.amp.blue.templates.FreemarkerAdapterJobj
And if I iterate as a list (ie <#list blah as x>) I get
Expected a sequence or collection, but this has evaluated to a hash
any ideas?

found the solution - apparently freemarker wants you now to implement TemplateHashModelEx rather than TemplateHashModel in your object wrapper. When you do that it works great.

Related

How tu use a variable in if in ftl?

I am learning ftl and have problem with variables.
I have an element a which has its own subelement b.
I access the subelement with the following method:
a.getChild("b")
Now, I check whether a subelement has content in the following way:
<#if a.getChild("b").getData()?has_content>
and this works as expected.
Now, I wanted to shorten this if's syntax by doing the following:
<#assign b>${a.getChild("b")}</#assign>
<#if b.getData()?has_content>
However, this produces error:
For "." left-hand operand: Expected a hash, but this has evaluated to a string
What am I doing wrong and how do I eliminate the need for calling the getChild in ifs?
I have hundreds of ifs in my production environment which all use getChild, sometimes even multiple times if subelements are nested so it would be great if I could shorten the syntax by assigning a child element to a variable.
I just started learning ftl yesterday, so this might be stupid question, sorry.
Simply do <#assign b = a.getChild("b")>.
With ${a.getChild("b")} you've outputted a string which then was assigned.
See the documentation also: https://freemarker.apache.org/docs/ref_directive_assign.html

Empty ActiveRecord::Relations do not compare in RSpec

I simplified my RSpec comparison problem down to this:
expect(DetailObjective.all.limit(0)).to eq(DetailObjective.none)
which returns a failed result:
expected: #<ActiveRecord::Relation []>
got: #<ActiveRecord::Relation []>
(compared using ==)
which seems like they DO match? How do I compare these empty Relations? I do not want to compare something fake like be_empty as that tells nothing about the comparative structures, just content.
DetailObjective.all.limit(0) and DetailObjective.none both return a new instance of ActiveRecord::Relation, but eq returns false when the objects are not identical -- that is to say, they are not the same object. You can see this easily by assigning the output of each method to a local variable and checking its object_id -- they will be different.
I do not want to compare something fake like be_empty ...
Not sure what you mean by 'fake'. Collections are complex types -- comparing them is not like comparing integers. Are they the same when the have the same members? When the members are in the same order? When the members are the same class?
Comparing one empty collection with another empty collection doesn't seem to make much sense ... can you be explicit about what you are trying to accomplish here?

Exposing all the globals in FreeMarker

<#list .globals?keys as vals>
${vals}
</#list>
FreeMarker template error: For "?keys" left-hand operand: Expected an extended
hash, but this has evaluated to a hash (wrapper: f.c.Environment$4):
==> .globals [in template "contents/globals.ftl" at line 9, column 8]
In other words, how to render the keys of a hash which is not extended in FreeMarker? (I'm using node.js with fmpp, rather than developing in Java)
As already stated in the comments, the keys of globals are not accessible. globals are a hash and no extended hash. This means, you can not access their keys and values using the built-ins for hashes.
You can tell if a hash is extended (and thus supports those built-ins) by using is_hash_ext.

Updating Hash Values in Ruby Clarified

I was going to comment on the original question but I don't have the reputation to do so yet....
I too was wondering how to easily update all the values in a hash, or if there was some kind of equivalent .map! method for hashes. Someone put up this elegant solution:
hash.update(hash){|key,v1| expresion}
on this question:
Ruby: What is the easiest method to update Hash values?
My questions is how does the block know to iterate over each element in the hash? For example, I'd have to call .each on a hash to access each element normally so why isn't it something like:
hash.update(hash.each) do |key ,value|
value+=1
end
In the block with {|key, value| expression} I am accessing each individual hash element yet I don't have to explicitly tell the system this? Why not? Thank you very much.
Hash#update is an alias for Hash#merge! which is more descriptive.
When calling the method with a block, the following happens (excerpt from the docs):
If [a] block is specified, [...] the value of each duplicate key is
determined by calling the block with the key [...]
So, the above code works like this:
The hash is merged with itself, and for each duplicate key the block is called. As we merge the hash with itself, every newly added key is a duplicate and therefore the block is invoked. The result is that every value in the hash gets replaced by expresion.
Hash#update takes a hash as the first parameter, and an optional block as the second parameter. If the second parameter is left out, the method will internally loop on each key-value pair in the supplied hash and use them to merge into the original hash.
If the block (second parameter) is supplied, the method does exactly the same thing. It loops over each key-value in the supplied hash and merges it in. The only difference is where a collision is found (the original hash already has an entry for a specific key). In this case the block is called to help resolve the conflict.
Based on this understanding, simply passing the hash into itself will cause it to loop over every key-value because that's how update always works. Calling .each would be redundant.
To see this more clearly, take a look at the source code for the #update method, and note the internal call to rb_hash_foreach in either logic branch.

Most Rubyish Way To Get An Array Containing Specific Values From An Array Of Objects?

I have an array of ruby objects that looks something like this:
[#<email: "someemail" other_properties: "SDFDF">, #<...>, #<...>]
Each of the objects in the array has an email property. I want to get a new array of all the email properties of the ruby objects in the array.
After executing the code, I would have an array that looked like this:
["email#example.com", "anotheremail#gmail.com", ...]
I am newer to ruby and want to do this in the most rubyish way possible.
My question is, what's the best way to do this in ruby?
You can use the map method to apply a block to each element of the array, returning a new array containing the results of each invocation:
somearray.map {|x| x.email}

Resources