1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Ruby] JSONをメソッドチェーンできるようにメタプログラミング

1
Last updated at Posted at 2016-09-21
Page 1 of 11

はじめに

こんなJSONをかえすAPIを想定しています

こんなJSONでレスポンスがきたら
[
    {"name": "general", "members": ["D29GZBAFQ", "D29RJ3PAG"]},
    {"name": "random",  "members": ["D29GZBJBQ", "D29RJ3PBG", "D29RJ3PCG"]}
]

したいこと

APIからJSONでデータを取得した時に、メソッドチェーンでアクセスしできたらいいなー
こんなかんじでアクセスできたら楽だろうなーと思って作ってみました


コンソール
client = Api::Client.new(url)

# チャンネルのレスポンス
client.result.channels # => [
                       #      {"name": "general", "members": ["D29GZBAFQ", "D29RJ3PAG"]},
                       #      {"name": "random",  "members": ["D29GZBJBQ", "D29RJ3PBG", "D29RJ3PCG"]}
                       #     ]


# チャンネルに登録しているメンバーID
client.result.channels.first.members # => ["D29GZBJBQ", "D29RJ3PBG", "D29RJ3PCG"]

現状はこんなかんじ

RubyでAPIを使う時の一般的な例

APIを叩くスクリプト
response_json = open(url).read
response_hash = JSON.parse(res)
response_hash.first["members"] # => ["D29GZBJBQ", "D29RJ3PBG", "D29RJ3PCG"]

したいこと
# これがしたい
response_hash.first.members    # => エラー

JSON.parseはHashを返すので、メソッドチェーンできずに失敗します


実装

api.rb
require 'open-uri'
require 'json'

class Hash
  # ここが実装のきもです。
  # Api::Client.new(url).resultはHashインスタンスを返しますが、
  # Hashインスタンスに対して`name`などのHashのkeyを呼んだ時に
  # self[:name]を返します
  def method_missing(name)
    return self[name].extend Hash if key? name
    self.each { |k, v| return v if k.to_s.to_sym == name }
    super.method_missing(name)
  end
end

module Api

  class Client
    attr_accessor :result
    def initialize(url)
      response = request(url)
      @result = parse(response)
    end

    private

    def request(url)
      open(url).read
    rescue SocketError => e
      puts "URLがちがうZE"
    end

    def parse(res)
      JSON.parse(res)
    rescue JSON::ParserError => e
      puts 'JSONじゃないZE'
      {}
    end

  end
end

できました

SlackAPIを叩いて、randomチャネルに登録しているユーザIDを取得してみます


コンソール
# このURLにアクセスしたい。今回はslackAPI
token = ENV['SLACK_TOKEN']
url = 'https://slack.com/api/channels.list?token=#{token}&pretty=1'

require '上記のファイルパス'

client = Api::Client.new(url)

# チャンネルのレスポンス
puts client.result.channels

# チャンネルに登録しているメンバーID
puts client.result.channels.first.members

実行結果
# チャンネルのレスポンス
[
    {"name": "general", "members": ["D29GZBAFQ", "D29RJ3PAG"]},
    {"name": "random",  "members": ["D29GZBJBQ", "D29RJ3PBG", "D29RJ3PCG"]}
]

# チャンネルに登録しているメンバーID
D29GZBJBQ
D29RJ3PBG
D29RJ3PCG

まとめ

SlackとかGithubのAPIで面白いもの作れそうですね!

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?