First off don't do HTTP calls straight from your controller.
Instead create a separate class that "talks" to the instagram API:
# app/clients/instagram_client.rb
class InstagramClient
include HTTParty
base_uri 'https://www.instagram.com'
format :json
def initialize(**options)
@options = options
end
def user(username, **opts)
options = @options.reverse_merge(
'__a' => 1 # wtf is this param?
).reverse_merge(opts)
response = self.class.get("/#{username}", options)
if response.success?
extract_user(response)
else
Rails.logger.error("Fetching Instagram feed failed: HTTP #{response.code}")
nil
end
end
private
def extract_user(json)
attributes = response.dig('graphql', 'user')&.slice('id', 'biography')
attributes ? InstagramUser.new(attributes) : nil
end
end
And an class that normalizes the API response for consumption in your application:
# app/models/instagram_user.rb
class InstagramUser
include ActiveModel::Model
include ActiveModel::Attributes
attribute :id
attribute :biography
attribute :username
# etc
end
This is just a straight up Rails model that is not persisted in the database. ActiveModel::Model and ActiveModel::Attributes let you pass a hash of attributes for mass assignment just like you do with ActiveRecord backed models.
This gives you an object you can simply test by:
InstagramClient.new.feed('elonofficiall')
And you would integrate it into your controller like so:
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
fetch_instagram(@user.instagram_username)
end
private
def fetch_instagram(instagram_username)
@instagram_user = InstagramClient.new.user(@user.instagram_username)
end
end
Mixing HTTParty into your controller is a straight up bad idea as controllers are tricky to test and the controller already has the responsibility of responding to client requests and does not need more.
Also processing a "raw" JSON response in your view is not a great practice as it creates a hard coupling between the external API and your application and adds far to much complexity to your views. Normalize the data first in a separate object.
<% if @instagram_user %>
<p><%= @instagram_user.username %></p>
<% end %>
If you want to actually get the media items from the users instagram feed you need to make another HTTP request to GET https://graph.facebook.com/{ig-user-id}/media. See the official API documentation.