Using different lists of the same content model in Middleman

Hey folks. I am building my first site with Middleman and Contentful using the Contentful Middleman extension.

I have a DateForYourDiary model with two fields e.g.

"fields": [
    {
      "id": "date",
      "name": "Date",
      "type": "Date",
      …
    },
    {
      "id": "description",
      "name": "Description",
      "type": "Symbol",
      …
    }
  ]

On my homepage, I want to show only the diary dates for this upcoming week, ordered in date order.

On another page, I want to show only past diary dates, ordered in reverse date order.

My config.rb includes:

activate :contentful do |f|
  f.space = Hash[ENV["CONTENTFUL_SPACE"], ENV["CONTENTFUL_SPACE"]]
  f.access_token = ENV["CONTENTFUL_ACCESS_TOKEN"]
  f.content_types = {diary_dates: "dateForYourDiary", school: "school", articles: "article"}
end

So I can access all diary_dates in my views with the following helper:

module ContentfulHelpers
  def diary_dates
    contentful_data.diary_dates
  end

  private

  def contentful_data
    data.send(ENV["CONTENTFUL_SPACE"])
  end
end

How can I extend my configuration so I have access to contentful_data.this_weeks_diary_dates and contentful_data.past_diary_dates? I know I could write ruby code to filter and sort diary_dates but I’m sure I should be taking advantage of Contentful’s API to do that work for me.

Many thanks
Mike

Hi there,

It would be possible to make use of our Delivery API with our order parameter to create both behaviours (in date order, and reversed).

However, in order to use it, you’d also have set only one content type in your query, as the fields are ultimately based on a each content type separately, and you’d need that for a successful query.

Let me know if that makes sense :slight_smile:

Thanks for your quick reply, Gabriel.

It makes sense but then opens up more questions!

  1. Would I be better off making calls using Contentful::Client rather than trying to sync everything into data with the contentful_middleman extension? Do you have an example of a best practice to set that up in Middleman e.g. not sure if it’s best to initiate Contentful::Client in config.rb, a helper or a new extension.

  2. How do I configure contentful_middleman to pull more than one content type and use a query? e.g. this in my config.rb will leave a data folder that only contains a school.

Presumably, the second activation overwrites the first.

activate :contentful do |f|
  f.space = Hash[ENV["CONTENTFUL_SPACE"], ENV["CONTENTFUL_SPACE"]]
  f.access_token = ENV["CONTENTFUL_ACCESS_TOKEN"]
  f.content_types = {diary_dates: "dateForYourDiary"}
  f.cda_query = # Some query here
end

activate :contentful do |f|
  f.space = Hash[ENV["CONTENTFUL_SPACE"], ENV["CONTENTFUL_SPACE"]]
  f.access_token = ENV["CONTENTFUL_ACCESS_TOKEN"]
  f.content_types = {school: "school"}
end
  1. Is it possible to map the same content type to multiple data?

e.g. something like this whereby both past_diary_dates and this_weeks_diary_dates are calling the dateForYourDiary content type:

activate :contentful do |f|
  f.space = Hash[ENV["CONTENTFUL_SPACE"], ENV["CONTENTFUL_SPACE"]]
  f.access_token = ENV["CONTENTFUL_ACCESS_TOKEN"]
  f.content_types = {past_diary_dates: "dateForYourDiary"}
  f.cda_query = # Query for past dates here
end

activate :contentful do |f|
  f.space = Hash[ENV["CONTENTFUL_SPACE"], ENV["CONTENTFUL_SPACE"]]
  f.access_token = ENV["CONTENTFUL_ACCESS_TOKEN"]
  f.content_types = {this_weeks_diary_dates: "dateForYourDiary"}
  f.cda_query = # Query for this week's dates here
end

Thanks again,
Mike

Hey @m_contentful,

I’m David, the maintainer of the Middleman integration,

Sadly, there’s no way of guaranteeing sort order after the import, as the rendered files are then indexed by ID, which are randomly generated. You can, however sort them when consuming them, by doing something like:

last_week_diary_dates = diary_dates.select { |_, diary_date| diary_date.date >= 1.week.ago }
ordered_diary_dates = last_week_diary_dates.sort { |_, diary_date| diary_date.date }

That is assuming the field is called date.

If you don’t need your diary dates older than one week at all, then, you can filter them on the CDA query directly as Gabriel suggested.

Hope this helps,

Cheers

I know I could write ruby code to filter and sort diary_dates but I’m sure I should be taking advantage of Contentful’s API to do that work for me.

Sounds like my original thought was wrong and you’d recommend filtering and sorting data rather than dropping down to using Contentful::Client.

Many thanks for your help, Gabriel and David!

For anyone reading this thread.

last_week_diary_dates = diary_dates.select { |_, diary_date| diary_date.date >= 1.week.ago }
ordered_diary_dates = last_week_diary_dates.sort { |_, diary_date| diary_date.date }

Should be:

last_week_diary_dates = diary_dates.select { |_, diary_date| diary_date.date >= 1.week.ago }
ordered_diary_dates = last_week_diary_dates.sort_by{ |_, diary_date| diary_date.date }

Where sort_by allows us to specify the .date attribute as the thing to sort by. :grinning:

1 Like

Hey @m_contentful,

Thanks for updating the snippet, I wrote it off the top of my head :sweat_smile:

Cheers

I hate to admit that it took me far too long to spot - went yak shaving for a while there!