[英]Reading Instagram JSON with Ruby Controller and passing to View, using HTTParty gem
我正在嘗試學習用 Ruby 處理 JSON。 我經歷了很多教程,但更加困惑,所以我嘗試通過這樣做來學習。
在這里,我試圖從 Instagram 獲取用戶數據並顯示在我的視圖中。 我可以訪問下面的 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 %>
首先不要直接從控制器進行 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::Model
和ActiveModel::Attributes
使您可以像使用 ActiveRecord 支持的模型一樣傳遞用於批量分配的屬性散列。
這為您提供了一個對象,您可以通過以下方式簡單地進行測試:
InstagramClient.new.feed('elonofficiall')
你可以像這樣將它集成到你的控制器中:
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
混合到您的控制器中是一個直接的壞主意,因為控制器很難測試,並且控制器已經負責響應客戶端請求並且不需要更多。
在您的視圖中處理“原始”JSON 響應也不是一個很好的做法,因為它在外部 API 和您的應用程序之間創建了一個硬耦合,並大大增加了您的視圖的復雜性。 首先在單獨的對象中規范化數據。
<% if @instagram_user %>
<p><%= @instagram_user.username %></p>
<% end %>
如果您想真正從用戶的 Instagram 提要中獲取媒體項目,您需要發出另一個 HTTP 請求來GET https://graph.facebook.com/{ig-user-id}/media
。 請參閱官方 API 文檔。
最好先把它從Rails
取出。 那只會使事情復雜化。 許多開發人員回復Rails
=== Ruby
。 它不是。
編寫一個簡單的 ruby 腳本並對其進行測試:
rec = HTTParty.get(url)
puts rec.headers # content-type is 'text/html' and should be 'application/json'
res = rec.parsed_response # getting error
puts res.class
Instagram 的問題在於,我認為它迫使用戶返回一個糟糕的content-header
。 它可能是一個安全層。 我似乎也無法將回復強制轉換為json
或hash
。 所以這就是httparty
不適合我的原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.