すること
今回はGET statuses/oembed — Twitter Developersを用いてツイッターカードを表示します。
埋め込みHTMLを取得するためには認証は必要ないので、単純なリクエストでデータを取得することが可能です。
流れは以下の通りです。
- 入力されたURLからIDを取得
- リクエストを送信してデータを取得
- URL, jsonをデータベースに保存
- 保存したデータを表示
開発環境
Ruby 2.6.5
Rails 5.2.3
MySQL 8.0.19
コントローラ
別段珍しいことはしていません。
redirect_to, renderは適当です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
|
モデル
事前に、jsonを入れる予定のt_json
カラムをマイグレーションで作成しておきます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
|
このままでは、入力したurlしか保存されません。ということで、urlからt_jsonを取得し保存するまでの流れを順に追っていきます。
1. 入力されたURLからIDを取得
URLは、例えばhttps://twitter.com/Interior/status/507185938620219395
という形になりますが、リクエストに必要なのはIDの507185938620219395
の部分だけです。
ということで、入力されたURLからIDとなる文字列を抜き出すtweet_id
というインスタンスメソッドを作成します。
1
2
3
|
def tweet_id
url.split('/').last
end
|
ちなみに、tweet.tweet_id
というような書き方で、モデルの外部からもIDを取得できます。
2. リクエストを送信してデータを取得
TwitterAPIにGETリクエストを送ります。
curlコマンドでは以下のようなコマンドになります。
1
|
$ curl 'https://publish.twitter.com/oembed?url=https%3A%2F%2Ftwitter.com%2FInterior%2Fstatus%2F507185938620219395'
|
これをRubyで実装します。2つの方法を挙げます。
open_uriを用いる方法
1
2
3
4
5
|
def tweet_json
url = "https://publish.twitter.com/oembed?url=https%3A%2F%2Ftwitter.com%2FInterior%2Fstatus%2F#{tweet_id}"
responce = OpenURI.open_uri(url) # リクエストを送り、返り値をresponceに代入
ActiveSupport::JSON.decode(responce.read)
end
|
Net::HTTPを用いる方法
1
2
3
4
5
6
|
def tweet_json
url = "https://publish.twitter.com/oembed?url=https%3A%2F%2Ftwitter.com%2FInterior%2Fstatus%2F#{tweet_id}"
uri = URI.parse(url)
responce = Net::HTTP.get(uri) # リクエストを送り、返り値をresponceに代入
JSON.parse(responce)
end
|
RubyのHTTPリクエストを送る方法の性能比較によると、Net::HTTP の方が速いようです。
これで以下のようなjson形式のデータを返すメソッドを作成できました。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
{
"url": "https://twitter.com/Interior/status/507185938620219395",
"author_name": "US Dept of Interior",
"author_url": "https://twitter.com/Interior",
"html": "<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Happy 50th anniversary to the Wilderness Act! Here's a great wilderness photo from <a href="https://twitter.com/YosemiteNPS">@YosemiteNPS</a>. <a href="https://twitter.com/hashtag/Wilderness50?src=hash">#Wilderness50</a> <a href="http://t.co/HMhbyTg18X">pic.twitter.com/HMhbyTg18X</a></p>— US Dept of Interior (@Interior) <a href="https://twitter.com/Interior/status/507185938620219395">September 3, 2014</a></blockquote>n<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>",
"width": 550,
"height": null,
"type": "rich",
"cache_age": "3153600000",
"provider_name": "Twitter",
"provider_url": "https://twitter.com",
"version": "1.0"
}
|
tweetを保存する前に、before_save
を用いてt_json
に値を入れることにします。
set_json
メソッドの役割は、URLが変更されていた場合、t_json
に値を入れるというものです。
外部APIを叩きすぎるのはよくないので、URLが変わっていない場合は特に変更しません(今回の例では他に変更しうるカラムがないので別に必要ないのですが)。
最終的なモデル
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
|
ビュー
Twitterカードを表示するにはjsonの"html"
をそのままHTMLとして出力すればいいので、ビューファイルで以下のように記述します。
1
|
<%= @tweet.t_json['html'].html_safe %>
|
ツイート情報を取得する際のオプション
1
|
"https://publish.twitter.com/oembed?url=https%3A%2F%2Ftwitter.com%2FInterior%2Fstatus%2F#{tweet_id}&omit_script=true"
|
このように&
でつなげます。(パラメータの種類については公式ページ参照)
omit_script=true
にすると、<script>
部分を除いたHTMLが返されるので、1ページに複数のツイートを表示する場合はおすすめです。
1
2
3
4
5
|
<% @tweets.each do |tweet| %>
<%= tweet.t_json['html'].html_safe %>
<% end %>
<%= javascript_include_tag '//platform.twitter.com/widgets.js' %>
|
リンク