thrillcall-api 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +10 -0
- data/.gitignore +10 -0
- data/.rspec +4 -0
- data/.rvmrc +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +58 -0
- data/README.md +1141 -0
- data/Rakefile +2 -0
- data/autotest/discover.rb +1 -0
- data/docs/API.html +1262 -0
- data/docs/API.md +1024 -0
- data/docs/README.html +1382 -0
- data/docs/WRAPPER.html +182 -0
- data/docs/WRAPPER.md +115 -0
- data/lib/thrillcall-api.rb +76 -0
- data/lib/thrillcall-api/exceptions.rb +7 -0
- data/lib/thrillcall-api/result.rb +142 -0
- data/lib/thrillcall-api/version.rb +3 -0
- data/script/convert_readme.rb +119 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/thrillcall-api/thrillcall-api_spec.rb +477 -0
- data/thrillcall-api.gemspec +34 -0
- metadata +201 -0
data/docs/WRAPPER.html
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
|
2
|
+
<style type="text/css">
|
3
|
+
.highlight .hll { background-color: #ffffcc }
|
4
|
+
.highlight { background: #dddddd; }
|
5
|
+
.highlight .c { color: #408080; font-style: italic } /* Comment */
|
6
|
+
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
7
|
+
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
|
8
|
+
.highlight .o { color: #666666 } /* Operator */
|
9
|
+
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
10
|
+
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
|
11
|
+
.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
12
|
+
.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
|
13
|
+
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
14
|
+
.highlight .ge { font-style: italic } /* Generic.Emph */
|
15
|
+
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
16
|
+
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
17
|
+
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
18
|
+
.highlight .go { color: #808080 } /* Generic.Output */
|
19
|
+
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
20
|
+
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
21
|
+
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
22
|
+
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
|
23
|
+
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
|
24
|
+
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
|
25
|
+
.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
|
26
|
+
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
|
27
|
+
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
|
28
|
+
.highlight .kt { color: #B00040 } /* Keyword.Type */
|
29
|
+
.highlight .m { color: #666666 } /* Literal.Number */
|
30
|
+
.highlight .s { color: #BA2121 } /* Literal.String */
|
31
|
+
.highlight .na { color: #7D9029 } /* Name.Attribute */
|
32
|
+
.highlight .nb { color: #008000 } /* Name.Builtin */
|
33
|
+
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
34
|
+
.highlight .no { color: #880000 } /* Name.Constant */
|
35
|
+
.highlight .nd { color: #AA22FF } /* Name.Decorator */
|
36
|
+
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
37
|
+
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
38
|
+
.highlight .nf { color: #0000FF } /* Name.Function */
|
39
|
+
.highlight .nl { color: #A0A000 } /* Name.Label */
|
40
|
+
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
41
|
+
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
|
42
|
+
.highlight .nv { color: #19177C } /* Name.Variable */
|
43
|
+
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
44
|
+
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
45
|
+
.highlight .mf { color: #666666 } /* Literal.Number.Float */
|
46
|
+
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
|
47
|
+
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
|
48
|
+
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
|
49
|
+
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
|
50
|
+
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
|
51
|
+
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
|
52
|
+
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
|
53
|
+
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
54
|
+
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
|
55
|
+
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
56
|
+
.highlight .sx { color: #008000 } /* Literal.String.Other */
|
57
|
+
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
|
58
|
+
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
|
59
|
+
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
|
60
|
+
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
|
61
|
+
.highlight .vc { color: #19177C } /* Name.Variable.Class */
|
62
|
+
.highlight .vg { color: #19177C } /* Name.Variable.Global */
|
63
|
+
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
|
64
|
+
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
|
65
|
+
</style><h1>Thrillcall API</h1>
|
66
|
+
|
67
|
+
<p>This document describes the Thrillcall API v2, and usage for the provided Ruby API wrapper gem.</p>
|
68
|
+
|
69
|
+
<h1>Ruby API Wrapper</h1>
|
70
|
+
|
71
|
+
<h3>Usage:</h3>
|
72
|
+
|
73
|
+
<div class="highlight">
|
74
|
+
<pre> <span class="c1">#---------------------------------------------------------------#</span>
|
75
|
+
<span class="c1"># First, require the gem:</span>
|
76
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
77
|
+
<span class="nb">require</span> <span class="s1">'rubygems'</span>
|
78
|
+
<span class="nb">require</span> <span class="s1">'thrillcall-api'</span>
|
79
|
+
|
80
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
81
|
+
<span class="c1"># Instantiate with your Thrillcall API key:</span>
|
82
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
83
|
+
<span class="no">MY_API_KEY</span> <span class="o">=</span> <span class="s2">"1234567890abcdef"</span>
|
84
|
+
<span class="n">tc</span> <span class="o">=</span> <span class="no">ThrillcallAPI</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="no">MY_API_KEY</span><span class="p">)</span>
|
85
|
+
|
86
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
87
|
+
<span class="c1"># Access any endpoint directly from the instance</span>
|
88
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
89
|
+
<span class="c1"># This is like calling GET "/events"</span>
|
90
|
+
<span class="n">tc</span><span class="o">.</span><span class="n">events</span>
|
91
|
+
<span class="c1"># => [ {"id" => ... }, {...}, ...]</span>
|
92
|
+
|
93
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
94
|
+
<span class="c1"># Provide IDs as arguments</span>
|
95
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
96
|
+
<span class="c1"># GET "/event/1"</span>
|
97
|
+
<span class="n">tc</span><span class="o">.</span><span class="n">event</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
98
|
+
<span class="c1"># => {"id" => 1, ...}</span>
|
99
|
+
|
100
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
101
|
+
<span class="c1"># Provide parameters as arguments</span>
|
102
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
103
|
+
<span class="c1"># GET "/events?limit=5"</span>
|
104
|
+
<span class="n">events</span> <span class="o">=</span> <span class="n">tc</span><span class="o">.</span><span class="n">events</span><span class="p">(</span><span class="ss">:limit</span> <span class="o">=></span> <span class="mi">5</span><span class="p">)</span>
|
105
|
+
<span class="c1"># => [ {"id" => ... }, {...}, ...]</span>
|
106
|
+
<span class="n">events</span><span class="o">.</span><span class="n">length</span>
|
107
|
+
<span class="c1"># => 5</span>
|
108
|
+
|
109
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
110
|
+
<span class="c1"># Chain methods together for nested routes</span>
|
111
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
112
|
+
<span class="c1"># GET "/search/venues/warfield?postalcode=94101&radius=20"</span>
|
113
|
+
<span class="n">venues</span> <span class="o">=</span> <span class="n">tc</span><span class="o">.</span><span class="n">search</span><span class="o">.</span><span class="n">venues</span><span class="p">(</span><span class="s2">"warfield"</span><span class="p">,</span> <span class="ss">:postalcode</span> <span class="o">=></span> <span class="s2">"94101"</span><span class="p">,</span> <span class="ss">:radius</span> <span class="o">=></span> <span class="mi">20</span><span class="p">)</span>
|
114
|
+
<span class="c1"># => [{"name" => "The Warfield", ...}]</span>
|
115
|
+
</pre>
|
116
|
+
</div>
|
117
|
+
|
118
|
+
|
119
|
+
<h3>Advanced Usage:</h3>
|
120
|
+
|
121
|
+
<p>Provide additional instantiation options:</p>
|
122
|
+
|
123
|
+
<div class="highlight">
|
124
|
+
<pre> <span class="c1">#---------------------------------------------------------------#</span>
|
125
|
+
<span class="c1"># The default SSL endpoint is "https://api.thrillcall.com/api/".</span>
|
126
|
+
<span class="c1"># The default API version is 2.</span>
|
127
|
+
<span class="c1"># By default, Faraday access logging is turned off.</span>
|
128
|
+
<span class="c1"># Override if necessary:</span>
|
129
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
130
|
+
<span class="n">tc</span> <span class="o">=</span> <span class="no">ThrillcallAPI</span><span class="o">.</span><span class="n">new</span><span class="p">(</span>
|
131
|
+
<span class="no">MY_API_KEY</span><span class="p">,</span>
|
132
|
+
<span class="ss">:base_url</span> <span class="o">=></span> <span class="s2">"https://api.thrillcall.com/custom/"</span><span class="p">,</span>
|
133
|
+
<span class="ss">:version</span> <span class="o">=></span> <span class="mi">3</span><span class="p">,</span>
|
134
|
+
<span class="ss">:logger</span> <span class="o">=></span> <span class="kp">true</span>
|
135
|
+
<span class="p">)</span>
|
136
|
+
</pre>
|
137
|
+
</div>
|
138
|
+
|
139
|
+
|
140
|
+
<p>Internally, the wrapper returns a ThrillcallAPI::Result class for any call. Data for the request is fetched only when used. This allows you to build requests piecemeal before executing them.</p>
|
141
|
+
|
142
|
+
<div class="highlight">
|
143
|
+
<pre> <span class="c1">#---------------------------------------------------------------#</span>
|
144
|
+
<span class="c1"># Build a partial request, add on to it later</span>
|
145
|
+
<span class="c1">#---------------------------------------------------------------#</span>
|
146
|
+
<span class="n">request</span> <span class="o">=</span> <span class="n">tc</span><span class="o">.</span><span class="n">artist</span><span class="p">(</span><span class="mi">22210</span><span class="p">)</span> <span class="c1"># Lady Gaga</span>
|
147
|
+
|
148
|
+
<span class="c1"># GET "/artist/22210/events?limit=2"</span>
|
149
|
+
<span class="n">artist_events</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">events</span><span class="p">(</span><span class="ss">:limit</span> <span class="o">=></span> <span class="mi">2</span><span class="p">)</span>
|
150
|
+
|
151
|
+
<span class="n">artist_events</span><span class="o">.</span><span class="n">length</span>
|
152
|
+
<span class="c1"># => 2</span>
|
153
|
+
</pre>
|
154
|
+
</div>
|
155
|
+
|
156
|
+
|
157
|
+
<p>This gem is a convenience wrapper around the excellent Faraday project. If more complicated use cases are necessary, consider using Faraday directly.</p>
|
158
|
+
|
159
|
+
<div class="highlight">
|
160
|
+
<pre> <span class="nb">require</span> <span class="s1">'faraday'</span>
|
161
|
+
<span class="nb">require</span> <span class="s1">'json'</span>
|
162
|
+
|
163
|
+
<span class="no">MY_API_KEY</span> <span class="o">=</span> <span class="s2">"1234567890abcdef"</span>
|
164
|
+
<span class="no">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://api.thrillcall.com/api/v2/"</span>
|
165
|
+
<span class="no">HEADERS</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">:accept</span> <span class="o">=></span> <span class="s1">'application/json'</span> <span class="p">}</span>
|
166
|
+
|
167
|
+
<span class="n">connection</span> <span class="o">=</span> <span class="no">Faraday</span><span class="o">.</span><span class="n">new</span><span class="p">(</span> <span class="ss">:url</span> <span class="o">=></span> <span class="no">BASE_URL</span><span class="p">,</span> <span class="ss">:headers</span> <span class="o">=></span> <span class="no">HEADERS</span> <span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">builder</span><span class="o">|</span>
|
168
|
+
<span class="n">builder</span><span class="o">.</span><span class="n">adapter</span> <span class="no">Faraday</span><span class="o">.</span><span class="n">default_adapter</span>
|
169
|
+
<span class="n">builder</span><span class="o">.</span><span class="n">response</span> <span class="ss">:logger</span>
|
170
|
+
<span class="n">builder</span><span class="o">.</span><span class="n">response</span> <span class="ss">:raise_error</span>
|
171
|
+
<span class="k">end</span>
|
172
|
+
|
173
|
+
<span class="n">request</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="n">get</span> <span class="k">do</span> <span class="o">|</span><span class="n">req</span><span class="o">|</span>
|
174
|
+
<span class="n">req</span><span class="o">.</span><span class="n">url</span> <span class="s2">"artist/22210"</span><span class="p">,</span> <span class="p">{</span> <span class="ss">:api_key</span> <span class="o">=></span> <span class="no">MY_API_KEY</span> <span class="p">}</span>
|
175
|
+
<span class="k">end</span>
|
176
|
+
|
177
|
+
<span class="n">artist</span> <span class="o">=</span> <span class="no">JSON</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">body</span><span class="p">)</span>
|
178
|
+
|
179
|
+
<span class="n">artist</span><span class="o">[</span><span class="s2">"name"</span><span class="o">]</span>
|
180
|
+
<span class="c1"># => "Lady Gaga"</span>
|
181
|
+
</pre>
|
182
|
+
</div>
|
data/docs/WRAPPER.md
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# Thrillcall API
|
2
|
+
This document describes the Thrillcall API v2, and usage for the provided Ruby API wrapper gem.
|
3
|
+
|
4
|
+
# Ruby API Wrapper
|
5
|
+
### Usage:
|
6
|
+
|
7
|
+
``` ruby
|
8
|
+
#---------------------------------------------------------------#
|
9
|
+
# First, require the gem:
|
10
|
+
#---------------------------------------------------------------#
|
11
|
+
require 'rubygems'
|
12
|
+
require 'thrillcall-api'
|
13
|
+
|
14
|
+
#---------------------------------------------------------------#
|
15
|
+
# Instantiate with your Thrillcall API key:
|
16
|
+
#---------------------------------------------------------------#
|
17
|
+
MY_API_KEY = "1234567890abcdef"
|
18
|
+
tc = ThrillcallAPI.new(MY_API_KEY)
|
19
|
+
|
20
|
+
#---------------------------------------------------------------#
|
21
|
+
# Access any endpoint directly from the instance
|
22
|
+
#---------------------------------------------------------------#
|
23
|
+
# This is like calling GET "/events"
|
24
|
+
tc.events
|
25
|
+
# => [ {"id" => ... }, {...}, ...]
|
26
|
+
|
27
|
+
#---------------------------------------------------------------#
|
28
|
+
# Provide IDs as arguments
|
29
|
+
#---------------------------------------------------------------#
|
30
|
+
# GET "/event/1"
|
31
|
+
tc.event(1)
|
32
|
+
# => {"id" => 1, ...}
|
33
|
+
|
34
|
+
#---------------------------------------------------------------#
|
35
|
+
# Provide parameters as arguments
|
36
|
+
#---------------------------------------------------------------#
|
37
|
+
# GET "/events?limit=5"
|
38
|
+
events = tc.events(:limit => 5)
|
39
|
+
# => [ {"id" => ... }, {...}, ...]
|
40
|
+
events.length
|
41
|
+
# => 5
|
42
|
+
|
43
|
+
#---------------------------------------------------------------#
|
44
|
+
# Chain methods together for nested routes
|
45
|
+
#---------------------------------------------------------------#
|
46
|
+
# GET "/search/venues/warfield?postalcode=94101&radius=20"
|
47
|
+
venues = tc.search.venues("warfield", :postalcode => "94101", :radius => 20)
|
48
|
+
# => [{"name" => "The Warfield", ...}]
|
49
|
+
```
|
50
|
+
|
51
|
+
### Advanced Usage:
|
52
|
+
|
53
|
+
Provide additional instantiation options:
|
54
|
+
|
55
|
+
``` ruby
|
56
|
+
|
57
|
+
#---------------------------------------------------------------#
|
58
|
+
# The default SSL endpoint is "https://api.thrillcall.com/api/".
|
59
|
+
# The default API version is 2.
|
60
|
+
# By default, Faraday access logging is turned off.
|
61
|
+
# Override if necessary:
|
62
|
+
#---------------------------------------------------------------#
|
63
|
+
tc = ThrillcallAPI.new(
|
64
|
+
MY_API_KEY,
|
65
|
+
:base_url => "https://api.thrillcall.com/custom/",
|
66
|
+
:version => 3,
|
67
|
+
:logger => true
|
68
|
+
)
|
69
|
+
|
70
|
+
```
|
71
|
+
|
72
|
+
Internally, the wrapper returns a ThrillcallAPI::Result class for any call. Data for the request is fetched only when used. This allows you to build requests piecemeal before executing them.
|
73
|
+
|
74
|
+
``` ruby
|
75
|
+
|
76
|
+
#---------------------------------------------------------------#
|
77
|
+
# Build a partial request, add on to it later
|
78
|
+
#---------------------------------------------------------------#
|
79
|
+
request = tc.artist(22210) # Lady Gaga
|
80
|
+
|
81
|
+
# GET "/artist/22210/events?limit=2"
|
82
|
+
artist_events = request.events(:limit => 2)
|
83
|
+
|
84
|
+
artist_events.length
|
85
|
+
# => 2
|
86
|
+
|
87
|
+
```
|
88
|
+
|
89
|
+
This gem is a convenience wrapper around the excellent Faraday project. If more complicated use cases are necessary, consider using Faraday directly.
|
90
|
+
|
91
|
+
``` ruby
|
92
|
+
|
93
|
+
require 'faraday'
|
94
|
+
require 'json'
|
95
|
+
|
96
|
+
MY_API_KEY = "1234567890abcdef"
|
97
|
+
BASE_URL = "https://api.thrillcall.com/api/v2/"
|
98
|
+
HEADERS = { :accept => 'application/json' }
|
99
|
+
|
100
|
+
connection = Faraday.new( :url => BASE_URL, :headers => HEADERS ) do |builder|
|
101
|
+
builder.adapter Faraday.default_adapter
|
102
|
+
builder.response :logger
|
103
|
+
builder.response :raise_error
|
104
|
+
end
|
105
|
+
|
106
|
+
request = connection.get do |req|
|
107
|
+
req.url "artist/22210", { :api_key => MY_API_KEY }
|
108
|
+
end
|
109
|
+
|
110
|
+
artist = JSON.parse(request.body)
|
111
|
+
|
112
|
+
artist["name"]
|
113
|
+
# => "Lady Gaga"
|
114
|
+
|
115
|
+
```
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
require "#{File.expand_path("../thrillcall-api/exceptions", __FILE__)}"
|
4
|
+
require "#{File.expand_path("../thrillcall-api/result", __FILE__)}"
|
5
|
+
require "#{File.expand_path("../thrillcall-api/version", __FILE__)}"
|
6
|
+
|
7
|
+
module ThrillcallAPI
|
8
|
+
class << self
|
9
|
+
attr_accessor :cur_api_key, :base, :result, :conn
|
10
|
+
|
11
|
+
# Set up the Faraday connection based on configuration
|
12
|
+
def new(cur_api_key, options = {})
|
13
|
+
default_options = {
|
14
|
+
:base_url => "https://api.thrillcall.com/api/",
|
15
|
+
:version => 2,
|
16
|
+
:logger => false
|
17
|
+
}
|
18
|
+
|
19
|
+
opts = default_options.merge(options)
|
20
|
+
|
21
|
+
@cur_api_key = cur_api_key
|
22
|
+
base_url = opts[:base_url]
|
23
|
+
version = opts[:version]
|
24
|
+
logger = opts[:logger]
|
25
|
+
|
26
|
+
# Make sure the base_url is in the form https://.../
|
27
|
+
unless base_url.match /^(http|https):\/\//
|
28
|
+
base_url = "https://" + base_url
|
29
|
+
end
|
30
|
+
|
31
|
+
unless base_url.match /\/$/
|
32
|
+
base_url = base_url + "/"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Set JSON accept header and custom user agent
|
36
|
+
@headers = {
|
37
|
+
:accept => 'application/json',
|
38
|
+
:user_agent => "Thrillcall API Wrapper version #{ThrillcallAPI::VERSION}"
|
39
|
+
}
|
40
|
+
|
41
|
+
@base = "#{base_url}v#{version}/"
|
42
|
+
@conn = Faraday.new( :url => @base, :headers => @headers ) do |builder|
|
43
|
+
builder.adapter Faraday.default_adapter
|
44
|
+
if logger
|
45
|
+
builder.response :logger
|
46
|
+
end
|
47
|
+
# This will raise an exception if an error occurs during a request
|
48
|
+
builder.response :raise_error
|
49
|
+
end
|
50
|
+
|
51
|
+
@result = Result.new
|
52
|
+
|
53
|
+
return self
|
54
|
+
end
|
55
|
+
|
56
|
+
def get(endpoint, params)
|
57
|
+
r = @conn.get do |req|
|
58
|
+
req.url endpoint, params.merge(:api_key => @cur_api_key)
|
59
|
+
end
|
60
|
+
JSON.parse(r.body)
|
61
|
+
end
|
62
|
+
|
63
|
+
def post(endpoint, params)
|
64
|
+
r = @conn.post do |req|
|
65
|
+
req.url endpoint, params.merge(:api_key => @cur_api_key)
|
66
|
+
end
|
67
|
+
JSON.parse(r.body)
|
68
|
+
end
|
69
|
+
|
70
|
+
def method_missing(method, *args, &block)
|
71
|
+
r = Result.new
|
72
|
+
r.send(method, args, block)
|
73
|
+
return r
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# Adapted from
|
2
|
+
# http://stackoverflow.com/questions/1332404/how-to-detect-the-end-of-a-method-chain-in-ruby
|
3
|
+
# and
|
4
|
+
# http://blog.jayfields.com/2008/02/ruby-replace-methodmissing-with-dynamic.html
|
5
|
+
|
6
|
+
module ThrillcallAPI
|
7
|
+
class Result
|
8
|
+
attr_accessor :ran, :request_keys, :options, :set_methods, :http_method
|
9
|
+
attr_reader :data
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
reset
|
13
|
+
end
|
14
|
+
|
15
|
+
def reset
|
16
|
+
if @set_methods
|
17
|
+
unset_methods
|
18
|
+
end
|
19
|
+
@ran = false
|
20
|
+
@data = {} # could be an array after fetch
|
21
|
+
@end_of_chain_is_singular = false
|
22
|
+
@options = {}
|
23
|
+
@request_keys = []
|
24
|
+
@set_methods = []
|
25
|
+
@http_method = :get
|
26
|
+
end
|
27
|
+
|
28
|
+
# Removes any dynamically defined methods
|
29
|
+
def unset_methods
|
30
|
+
@set_methods.each do |s|
|
31
|
+
(class << self; self; end).class_eval do
|
32
|
+
undef_method s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
@set_methods = []
|
37
|
+
end
|
38
|
+
|
39
|
+
# Dynamically defines any methods available to data.
|
40
|
+
# i.e. it puts on a "#{data.class}" costume
|
41
|
+
def reassign(data)
|
42
|
+
unset_methods
|
43
|
+
|
44
|
+
data.public_methods(false).each do |meth|
|
45
|
+
@set_methods << meth
|
46
|
+
(class << self; self; end).class_eval do
|
47
|
+
define_method meth do |*args, &block|
|
48
|
+
data.send meth, *args, &block
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Append the name of the method and any args to the current
|
55
|
+
# request being built
|
56
|
+
def append(key, *args)
|
57
|
+
|
58
|
+
# If this is called but we've already fetched data, reset
|
59
|
+
if @ran
|
60
|
+
reset
|
61
|
+
end
|
62
|
+
|
63
|
+
@request_keys << key
|
64
|
+
|
65
|
+
if args
|
66
|
+
if args.is_a? Array
|
67
|
+
args = args.flatten
|
68
|
+
end
|
69
|
+
args.each do |arg|
|
70
|
+
if arg
|
71
|
+
a = arg
|
72
|
+
if a.is_a? Hash
|
73
|
+
# Merge this hash on top of the existing options
|
74
|
+
@options.merge!(a)
|
75
|
+
else
|
76
|
+
# This is an ID or search term, add it directly to the
|
77
|
+
# list of keys
|
78
|
+
@request_keys << a.to_s
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def run(method, *args, &block)
|
86
|
+
# Fetch data if necessary. This will also "put on the
|
87
|
+
# data.class costume" and allow the method to respond to a
|
88
|
+
# subsequent send()
|
89
|
+
if !@ran
|
90
|
+
fetch_data
|
91
|
+
end
|
92
|
+
|
93
|
+
# Send the requested method out to the newly defined method
|
94
|
+
self.send(method, *args, &block)
|
95
|
+
end
|
96
|
+
|
97
|
+
def fetch_data
|
98
|
+
url = URI.escape(@request_keys.join("/"))
|
99
|
+
|
100
|
+
@data = ThrillcallAPI.send(@http_method, url, @options)
|
101
|
+
|
102
|
+
# Now we define the instance methods present in the data object
|
103
|
+
# so that we can use this object *as if* we are using the data
|
104
|
+
# object directly and we don't encounter method_missing
|
105
|
+
reassign(@data)
|
106
|
+
|
107
|
+
@ran = true
|
108
|
+
end
|
109
|
+
|
110
|
+
def post(args = {})
|
111
|
+
if @ran
|
112
|
+
raise ArgumentError, "This request has already been made!"
|
113
|
+
else
|
114
|
+
@http_method = :post
|
115
|
+
@options.merge!(args)
|
116
|
+
fetch_data
|
117
|
+
end
|
118
|
+
@data
|
119
|
+
end
|
120
|
+
|
121
|
+
def method_missing(method, *args, &block)
|
122
|
+
|
123
|
+
if @ran
|
124
|
+
# NoMethodError
|
125
|
+
super
|
126
|
+
else
|
127
|
+
# We haven't fetched the data yet, but if this method is for
|
128
|
+
# a hash or an array, we'd better.
|
129
|
+
# The bad news about this technique is that we can't have any
|
130
|
+
# endpoints that map to array or hash methods
|
131
|
+
if {}.respond_to?(method) || [].respond_to?(method)
|
132
|
+
r = run(method, *args, &block)
|
133
|
+
return r
|
134
|
+
else # Keep building the request
|
135
|
+
append(method, *args)
|
136
|
+
return self
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|