読者です 読者をやめる 読者になる 読者になる

ここにタイトルが入ります

デザイン&プログラミングのことも書くし、それ以外のことも書く。

【Rails】ActiveResourceを使用してYouTube動画を取得する

Rails my works

今回は「ActiveResource」を使って、YouTubeAPIを通しての画像取得にトライしました。
入力された検索ワードを使って検索し、引っかかった動画の情報を取得し表示したいためです。


ActiveResourceとは

RailsActiveRecordを使用していると、Model経由でDBのデータを取得したり更新したりできますが、
ActiveResourceを使用すると、WebApiで取得してきたデータもModel経由で取得できるようにできます!

ViewやcontrollerからはDBとかAPIとかどこから取得してきたかを意識することなく、
同じようにModelからデータを操作することができます。

Railsデフォルトの機能ですね。


〜参考にさせて頂きました!〜
ActiveResource の使い方(前編) : Rails 同士で通信する - WebOS Goodies
ActiveResource::Base


YouTubeモデルの作成


コンソールから

Rails g model youtube

みたいなのを実行してYouTubeモデルを作成したら、
継承するクラスを「ActiveRecord」から「ActiveResource」に変更します。

class Youtube < ActiveResource::Base #ここ
end

で、そのクラスの中に基本設定と取得ロジックを作成します。

class Youtube < ActiveResource::Base

  self.site = "http://gdata.youtube.com"

  def self.videos(search_word)
    self.find(:one, from: "/feeds/api/videos", params: { q: search_word , :"max-results" => 10, alt: "json"} )
  end

end

site

まずsite変数に取得先のサーバー名を指定します。
そしてvideosメソッドを作ってあげて、site.findでYouTubeから画像情報を取得するようにします。

findメソッド

引数一つ目ですが、idを渡すかシンボル:all,:first,lastを指定し取得するオブジェクトを指定します。
ただ今回のように引数2つ目の:fromでパスを直指定する場合、:oneという指定もできるらしい。


…ごめんなさい、ここに関しては私よくわかっていません(^_^;)
下記に説明があったのでもし良ければそちらの方を…
ActiveResource の使い方(前編) : Rails 同士で通信する - WebOS Goodies


今回は:oneじゃないとうまく行きませんでした。
指定したIDによって対応するオブジェクトが返却される、みたいなAPIじゃなく
指定したURIを叩くとjsonがまるごとドカンと返ってくるようなリクエストだから…???


paramsにはクエリパラメータをハッシュで渡せます。
以下を見ながら作成。
デベロッパー ガイド: Data API プロトコル - API クエリ パラメータ - YouTube — Google Developers
ある検索ワードで検索し、10件のデータをjsonで返却してくれというリクエストですね。


しかし、このままでは動きませんでした…


Formatクラスを修正

動かすと謎の"NameError”が発生。。
先輩が見つけてくれたのですが、どうやら返ってくるjsonデータに原因があるようで…

ActiveResourceは、返ってきたjsonデータの中身をModelのAttributeとして用意してくれます。
entryという項目があれば、モデル.entryとすればentryが取得できるわけです。
モデルの中にentryメソッドを作成してくれてるんですね。

…で、YoutubeAPIが返してくれる項目名の中に$が含まれるものがあったんですね。
Rubyではメソッド名の中に$を含むことはできませんから、NameErrorとなってしまったようです。

という訳で、jsonフォーマットを修正します。

class Youtube < ActiveResource::Base

  self.site = "http://gdata.youtube.com"

  # ↓追加
  class Format
    include ActiveResource::Formats::JsonFormat
    def decode(json)
      super(json.gsub("$","_"))
    end
  end

  self.format = Format.new
  # ↑追加

  def self.videos(search_word)
    self.find(:one, from: "/feeds/api/videos", params: { q: search_word , :"max-results" => 10, alt: "json"} )
  end

end

これで、jsonで取得した時には$を_に変更するようフォーマットが変更出来ました。
もし項目にhoge$entryのようなデータが含まれていた場合、
モデル.hoge_entryという形で取得できます。


これでとりあえず、youtubeモデルのvideosメソッドを叩けば
画像情報が取得できるようになりました!\(^o^)/
view側で取得したデータを煮るなり焼くなりしましょう。



やってみたサンプルソース
https://github.com/fumihiro/musician_search