0

I'm running a rails application that calls Simplecasts API to display my podcast episodes. I followed a tutorial to setup the API services using Faraday. My question is how to only display published episodes on my index page? Normally, I would add a .where(:status => "live") in my controller, IE @podcasts = Episodes.where(:status => "published") but this doesn't seem to work.

Simplecast's API for the podcast returns a collection that contains all the available episodes, each has a status node.

Any help would be appreciated as I'm new to working with external APIs in Rails

Sample API response

"collection": [
    {
        "updated_at": "2020-03-25T17:57:00.000000-04:00",
        "type": "full",
        "token": "lgjOmFwr",
        "title": "Test",
        "status": "draft",

Episode.rb

module Simplecast
  class Episodes < Base
    attr_accessor :count,
                  :slug,
                  :title,
                  :status

    MAX_LIMIT = 10

    def self.episodes(query = {})
      response = Request.where('/podcasts/3fec0e0e-faaa-461f-850d-14d0b3787980/episodes', query.merge({ number: MAX_LIMIT }))
      episodes = response.fetch('collection', []).map { |episode| Episode.new(episode) }
      [ episodes, response[:errors] ]
    end

    def self.find(id)
      response = Request.get("episodes/#{id}")
      Episode.new(response)
    end

    def initialize(args = {})
      super(args)
      self.collection = parse_collection(args)
    end

    def parse_collection(args = {})
      args.fetch("collection", []).map { |episode| Episode.new(episode) }
    end
  end
end

Controller

class PodcastsController < ApplicationController
  layout "default"


  def index

    @podcasts, @errors = Simplecast::Episodes.episodes(query)

    @podcast, @errors = Simplecast::Podcast.podcast(query)

    render 'index'
  end

  # GET /posts/1
  # GET /posts/1.json
  def show
    @podcast = Simplecast::Episodes.find(params[:id])
    respond_to do |format|
      format.html
      format.js
    end
  end

  private
    def query
      params.permit(:query, {}).to_h
    end
end

1 Answers1

0

Looks like collection is just an array of hashes so rails ActivrRelations methods aka .where are not supported. However It is an array so you can just filter this array:

published_episodes = collection.filter { |episode| episode[:status] == “ published” }

Also look through their API - may be the do support optional filtering params so you would get only published episodes in the first place.

BTW: second thought is to save external API request data in your own DB and then fetch require episodes with standard .where flow.

  • Thanks. Is there a way to combine it with this to map only the published episodes? `episodes = response.fetch('collection', []).map { |episode| Episode.new(episode) }` – Arash Hadipanah Apr 23 '20 at 13:05
  • You bet there is, it is Ruby: https://ruby-doc.org/core-2.7.0/Enumerable.html#method-i-filter_map. Also it would be a nice decision I separate this two operations in explicit methods - fetching from api and mapping on your models. Single responsibility - S for SOLID – Victor Shinkevich Apr 25 '20 at 03:25