ruby-on-rails - 使用 Ruby Controller 读取 Instagram JSON 并使用 HTTParty gem 传递到 View

标签 ruby-on-rails json http methods httparty

我正在尝试学习使用 Ruby 处理 JSON。我浏览了很多教程,但更加困惑,所以我尝试边做边学。

在这里,我尝试从 Instagram 获取用户数据并显示在我的 View 中。我可以访问下面的 JSON,但是如何访问某些字段和用户名或循环帖子?

# users_controller.rb
require 'httparty'

class UsersController < ApplicationController
    include HTTParty

    def show
        @user = User.find(params[:id])
        fetch_instagram("elonofficiall")
    end

    private
    def fetch_instagram(instagram_username)
        url = "https://www.instagram.com/#{instagram_username}/?__a=1"
        @data = HTTParty.get(url)
        return @data
    end
end

# show.html.erb
# the code below is just to try if I get anything
<%= @data %>
<% @data.each do |data| %>
  <p><%= data %></p>
<% end %>

https://www.instagram.com/elonofficiall/?__a=1

enter image description here

最佳答案

首先不要直接从 Controller 进行 HTTP 调用。

而是创建一个单独的类来与 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

以及一个标准化 API 响应以供应用程序中使用的类:

# app/models/instagram_user.rb
class InstagramUser
  include ActiveModel::Model
  include ActiveModel::Attributes
  attribute :id
  attribute :biography
  attribute :username
  # etc
end

这只是一个直接的 Rails 模型,未保存在数据库中。 ActiveModel::ModelActiveModel::Attributes 让您可以传递属性的哈希值以进行批量分配,就像使用 ActiveRecord 支持的模型一样。

这为您提供了一个可以简单测试的对象:

InstagramClient.new.feed('elonofficiall')

您可以将其集成到您的 Controller 中,如下所示:

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

HTTParty 混合到 Controller 中是一个彻头彻尾的坏主意,因为 Controller 很难测试,而且 Controller 已经负责响应客户端请求,不需要更多。

在您的 View 中处理“原始”JSON 响应也不是一个好的做法,因为它会在外部 API 和您的应用程序之间创建硬耦合,并大大增加您的 View 的复杂性。首先在单独的对象中标准化数据。

<% if @instagram_user %>
  <p><%= @instagram_user.username %></p>
<% end %>

如果您想实际从用户的 Instagram Feed 获取媒体项目,您需要向 GET https://graph.facebook.com/{ig-user-id}/media 发出另一个 HTTP 请求.请参阅official API documentation .

关于ruby-on-rails - 使用 Ruby Controller 读取 Instagram JSON 并使用 HTTParty gem 传递到 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63820669/

相关文章:

ruby-on-rails - rails : Postgres + rake db:structure:dump using wrong user

javascript - 将多个 OBJ 中的数据检索到仅一个 OBJ javascript 函数

javascript - 如何从以下 json 中获取 key

http - 开发网络服务器有哪些不同的方法?

ruby-on-rails - 如何从 Time.now 获取时区偏移

ruby-on-rails - 自动创建 rails locale yaml 文件?

javascript - 如何在 Angular Accordion 中停止不必要的空容器 [循环]

http - 带有 HTTP/2 的 REST API

windows - 如何实现WebServiceHost认证?

ruby-on-rails - Rails 自定义 css 链接不起作用 - 按照 http ://ruby. railstutorial.org 中的教程进行操作