Accessing yaml data array value by name

Hello,

On my site, I have a group of projects that I list out on a ‘projects’ page. Each project then has its own individual page, with a shared template.

The data structure is:

data/projects.yml

project_one
  title:
    "Project One"
  description:
    "Description of project one"
  year:
    2018

project_two
  title:
    "Project Two"
  description:
    "Description of project two"
  year:
    2018

I then manually list each project on the ‘projects’ page, and reuse the data on an individual page, both with:

<%= data.projects.project_two.title %>

This works at the moment, but it doesn’t scale well and any changes made to a project’s markup in the list has to be duplicated throughout the page.

I can easily change this to an array and loop through it, e.g.

data/projects.yml

- project_one
  title:
    "Project One"
  description:
    "Description of project one"
  year:
    2018

- project_two
  title:
    "Project Two"
  description:
    "Description of project two"
  year:
    2018
  <% unless data.work.nil? %>
    <ul>
      <% data.work.each do |f| %>
      <li>
        <h2><%= f.title %></h2>
        <p><%= f.description %></p>
      </li>
      <% end %>
    </ul>
  <% end %>

I’d then like to access specific project values for each project page, so, for example, if I have project-one.html.erb, I can display the title from the array.

I know this is possible with

  <%= data.work[0].title %>
  <%= data.work[0].description %>

But is it possible to access the hash value by key name? I’ve read a number of posts on the forum, and referenced some Ruby docs, and have seen references to something like:

  <%= data.work['project_two']['title'] %>

but that returns a no implicit conversion of String into Integer error, as I imagine its expecting an array integer. I have a basic understanding of Ruby methods but not certain what applies here.

The docs mention something similar using a proxy and auto-generated pages, but each of my project pages are heavily customized so generating on build isn’t an option. Alternatively, I’ve looked at building each project as a yaml file in a subdirectory (data/projects/project-one.yml) and then accessing them individually, both I’m not sure it’s feasible to loop through and output the subdirectories on an index page.

Thanks for any tips

Did you try the instance_eval function yet?

You should be able to keep the first version of your .yml file and access the fields with:

<%= data.projects.instance_eval('project_two').title %>

Thanks for the tip. While it does work with the first example, i.e. I can pull out the title on any given page like:

project_one
  title:
    "Project One"
  description:
    "Description of project one"
  year:
    2018

project_two
  title:
    "Project Two"
  description:
    "Description of project two"
  year:
    2018
<%= data.projects.instance_eval('project_two').year %>

But unfortunately I can’t iterate through a loop of that yaml data, e.g.

<% unless data.projects.nil? %>
  <% data.projects.each do |f| %>
    <%= f.title %>
  <% end %>
<% end %>

Using the second yaml example from my original post, I can iterate through a loop but I can’t access individual data.

(As an aside, isn’t instance_eval doing the same as <%= data.projects.project_two.year %> ?)

This Is exactly what I have been trying to accomplish. I have roughly 20 thousand pages I am trying to dynamically create from a data file. I know too that this is possible, however I’m new to middleman and Ruby.

Has any progress been made on this? I will keep looking, and hopefully find something soon.

I’ll repost with an answer if I find something.