thrillcall-api 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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"># =&gt; [ {"id" =&gt; ... }, {...}, ...]</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"># =&gt; {"id" =&gt; 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">=&gt;</span> <span class="mi">5</span><span class="p">)</span>
105
+ <span class="c1"># =&gt; [ {"id" =&gt; ... }, {...}, ...]</span>
106
+ <span class="n">events</span><span class="o">.</span><span class="n">length</span>
107
+ <span class="c1"># =&gt; 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&amp;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">=&gt;</span> <span class="s2">"94101"</span><span class="p">,</span> <span class="ss">:radius</span> <span class="o">=&gt;</span> <span class="mi">20</span><span class="p">)</span>
114
+ <span class="c1"># =&gt; [{"name" =&gt; "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">=&gt;</span> <span class="s2">"https://api.thrillcall.com/custom/"</span><span class="p">,</span>
133
+ <span class="ss">:version</span> <span class="o">=&gt;</span> <span class="mi">3</span><span class="p">,</span>
134
+ <span class="ss">:logger</span> <span class="o">=&gt;</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">=&gt;</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"># =&gt; 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">=&gt;</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">=&gt;</span> <span class="no">BASE_URL</span><span class="p">,</span> <span class="ss">:headers</span> <span class="o">=&gt;</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">=&gt;</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"># =&gt; "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,7 @@
1
+ module ThrillcallAPI
2
+ class Error < StandardError
3
+ def initialize(details = {})
4
+ super("#{details[:type]}: #{details[:message]}")
5
+ end
6
+ end
7
+ 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