Is it possible to read YAML array items directly using erb?

753 views
Skip to first unread message

Dave Everitt

unread,
Feb 24, 2013, 5:44:54 AM2/24/13
to na...@googlegroups.com
Is there a way for erb to access a specific array item from YAML directly?

---
terntest:
- tern1
- tern2
---

Here's what I'm doing now:

<%= tern = @item[:terntest]; tern[0] %>[some HTML here]<%= tern[1] %>

Here's one example what I thought would be possible (and several other failed variations after much time in erb docs/StackOverflow/anything_I_could_find before giving in and asking here):

<%= @item[:terntest[0]] %>[some HTML here]<%= @item[:terntest[1]] %>

Must a YAML array always be converted to a Ruby array before you can access it's items in an erb template?

Damien Pollet

unread,
Feb 24, 2013, 6:34:11 AM2/24/13
to na...@googlegroups.com
On 24 February 2013 11:44, Dave Everitt <deve...@innotts.co.uk> wrote:
<%= @item[:terntest[0]] %>[some HTML here]<%= @item[:terntest[1]] %>

it's a simple syntax error: you misplaced the [0], it should be out of the [] of @item, like so:

<%= @item[:terntest][0] %>[some HTML here]<%= @item[:terntest][1] %>

--
Damien Pollet
type less, do more [ | ] http://people.untyped.org/damien.pollet

Dave Everitt

unread,
Feb 24, 2013, 6:58:10 AM2/24/13
to na...@googlegroups.com
[longfacepalm] tried that first and it failed, but only because I'd changed more than one thing before testing again[/longfacepalm]. Thanks for your eyeballs, Damien.

Dave Everitt

unread,
Feb 24, 2013, 8:38:48 AM2/24/13
to na...@googlegroups.com
Okay, once again I'm gonna have to swallow my pride and ask... this time with hashes. I swear I've spent well over an hour searching for solutions and trying combinations (only just digging into YAML so it's unfamiliar territory)... e.g. (apparently integers are okay as keys)

myhash:
 1: item1
 3: item3
 2: item3

<%= @item[:myhash][1] %>

returns nothing, while

myhash:
 one: item1
 thr: item3
 two: item3

<%= @item[:myhash][one] %>

throws errors (as does quoting the key, either/both in the YAML and erb).

In the YAML I've also tried (since various sources appear ambiguous on the space dash space)

myhash:
 - 
  1: item1
  3: item3
  2: item3

Damien Pollet

unread,
Feb 24, 2013, 10:32:39 AM2/24/13
to na...@googlegroups.com
On 24 February 2013 14:38, Dave Everitt <deve...@innotts.co.uk> wrote:
Okay, once again I'm gonna have to swallow my pride and ask...

don't worry, the more I look into yaml the more I think it's stupid (too much variability and context-dependent syntax) 

myhash:
 1: item1
 3: item3
 2: item3

<%= @item[:myhash][1] %>

for this to work you'd want a sequence (unless, as I just saw, you really want the indices out of order):

myhash:
  - item1
  - item2

Yaml hashes might be using strings or symbols as keys, so try like this:
@item[:myhash]['1']
 
<%= @item[:myhash][one] %> 
 
throws errors (as does quoting the key, either/both in the YAML and erb).

yeah that's because in that expression, one is either a variable or a method call. you meant 'one' (literal string) or :one (literal symbol)
 
In the YAML I've also tried (since various sources appear ambiguous on the space dash space)

myhash:
 - 
  1: item1
  3: item3

this is equivalent to { myhash => [ {'1' => 'item1', '3' => 'item3'} ] } 

Dave Everitt

unread,
Feb 24, 2013, 6:05:36 PM2/24/13
to na...@googlegroups.com
don't worry, the more I look into yaml the more I think it's stupid (too much variability and context-dependent syntax) 

yep, bit of a minefield. I've just spent a year with JSON and it's hard to switch mindsets.
 
myhash:
 1: item1
 3: item3
 2: item3

for this to work you'd want a sequence (unless, as I just saw, you really want the indices out of order):

I did, but only if I can read them in order as well - the three items appear in two different orders, and I intended to use the numbers for one and the actual order for the other... if YAML hash pairs can be read in order.

Yaml hashes might be using strings or symbols as keys, so try like this:
@item[:myhash]['1']

no joy there - no error, but no value in the erb.
 
myhash:
 - 
  1: item1
  3: item3

this is equivalent to { myhash => [ {'1' => 'item1', '3' => 'item3'} ] } 

Ah... I see. Think I'll put up a new topic focussed on this YAML hash -> erb issue only. Thanks again :-)
Message has been deleted
Message has been deleted

Dave Everitt

unread,
Feb 25, 2013, 5:14:17 AM2/25/13
to na...@googlegroups.com
Since Ruby < 9 can't be guaranteed to read hash items in order, I added an extra array for the second ordering sequence:


terntest:
- tern1
- tern2
- tern3
n:
- 2
- 0
- 1

then :n can be used to sort :terntest in the erb - [:n][0] is the primary item (the sorting order for :terntest varies in each case) e.g.:

<%= @item[:terntest][@item[:n][2]] %>, (<%= @item[:terntest][@item[:n][0]] %>, <%= @item[:terntest][@item[:n][1]] %>)

Which generates:
tern3, (tern1, tern2)

The other sorting order simply reads :terntest in order.

Denis Defreyne

unread,
Mar 5, 2013, 2:57:28 AM3/5/13
to na...@googlegroups.com
Hi,

> terntest:
> - tern1
> - tern2
> - tern3

This is a Ruby array, which is always ordered, so this array is not necessary:

> n:
> - 2
> - 0
> - 1

Denis

Dave Everitt

unread,
Mar 5, 2013, 6:27:39 AM3/5/13
to na...@googlegroups.com
Hi Denis

I'm aware of that :-) but once I'd got around the 'doh' moment about reading arrays in erb, my later reply was because I then needed two distinct orders from different hashes, on many pages with different values and key orders, but all in this form with numerical keys:

ternhash:
- 2: tern1
- 0: tern2
- 1: tern3

where the values are ordered twice, like this:

* order one: order of appearance in the hash (tern1, tern2, tern3) - not reliable in Ruby <9;
* order two: numerical order of the hash key (tern2, tern3, tern1) - each page's hash has it's own order.

But I couldn't find out how to read a YAML hash by key in erb (@item[:terntest]['0']@item[:terntest][:0]?... nope, still can't!) so gave up and used the two-array solution, so the YAML in my content files is like this:

terntest:
- tern1
- tern2
- tern3

n:
- 2
- 0
- 1

and for the two orders required, my layouts read it like this:

order one:
<%= @item[:terntest].join(', ') %>

order two:
<%= @item[:terntest][@item[:n][0]] %>, <%= @item[:terntest][@item[:n][1]] %>, <%= @item[:terntest][@item[:n][2]] %>

Whereas if I used a hash, for order two I was expecting to be able to do something like:

<%= @item[:ternhash][:0]] %>, <%= @item[:ternhash][:1]] %>, <%= @item[:ternhash][:2]] %>

But that, and other attempts to read a hash, fail (I'll post another topic). In fact, I'm thinking of writing up simple 'how to read your YAML into erb and loop through arrays and stuff like that' because it's not easy to find. Of course, nanoc itself is not at fault in any of this :-)

Denis Defreyne

unread,
Mar 5, 2013, 6:34:47 AM3/5/13
to na...@googlegroups.com
On 05 Mar 2013, at 12:27, Dave Everitt <deve...@innotts.co.uk> wrote:

> [snip]
> But I couldn't find out how to read a YAML hash by key in erb (@item[:terntest]['0']? @item[:terntest][:0]?... nope, still can't!)

Have you tried :'0'? Sometimes, symbols need to be quoted, because :0 will not parse correctly.

Denis

Dave Everitt

unread,
Mar 5, 2013, 6:38:57 AM3/5/13
to na...@googlegroups.com
oops. The last erb example in the above post had one too many closing square brackets - should have been @item[:ternhash][:0]

Dave Everitt

unread,
Mar 5, 2013, 6:41:32 AM3/5/13
to na...@googlegroups.com
Yep, that fails too. TypeError: Symbol as array index
Reply all
Reply to author
Forward
0 new messages