spire_io 1.0.0.alpha.2 → 1.0.0.alpha.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/spire_io.rb +149 -485
  2. metadata +4 -5
  3. data/lib/requestable.rb +0 -70
data/lib/spire_io.rb CHANGED
@@ -1,205 +1,25 @@
1
+ require "delegate"
1
2
  gem "excon"
2
3
  require "excon"
3
4
  gem "json"
4
5
  require "json"
5
6
 
6
- require "requestable"
7
+ require "spire/api"
7
8
 
8
9
  class Spire
9
10
 
10
11
  #How many times we will try to create a channel or subscription after getting a 409
11
12
  RETRY_CREATION_LIMIT = 3
12
13
 
13
- include Requestable
14
-
15
- define_request(:discover) do
16
- {
17
- :method => :get,
18
- :url => @url,
19
- :headers => {"Accept" => "application/json"}
20
- }
21
- end
22
-
23
- define_request(:start) do |key|
24
- {
25
- :method => :post,
26
- :url => @description["resources"]["sessions"]["url"],
27
- :body => {:key => key}.to_json,
28
- :headers => {
29
- "Accept" => mediaType("session"),
30
- "Content-Type" => mediaType("account")
31
- }
32
- }
33
- end
34
-
35
- define_request(:login) do |email, password|
36
- {
37
- :method => :post,
38
- :url => @description["resources"]["sessions"]["url"],
39
- :body => { :email => email, :password => password }.to_json,
40
- :headers => {
41
- "Accept" => mediaType("session"),
42
- "Content-Type" => mediaType("account")
43
- }
44
- }
45
- end
46
-
47
- define_request(:register) do |info|
48
- {
49
- :method => :post,
50
- :url => @description["resources"]["accounts"]["url"],
51
- :body => {
52
- :email => info[:email],
53
- :password => info[:password],
54
- :password_confirmation => info[:password_confirmation]
55
- }.to_json,
56
- :headers => {
57
- "Accept" => mediaType("session"),
58
- "Content-Type" => mediaType("account")
59
- }
60
- }
61
- end
62
-
63
- define_request(:session) do
64
- {
65
- :method => :get,
66
- :url => @session["url"],
67
- :headers => {
68
- "Accept" => mediaType("session"),
69
- "Authorization" => "Capability #{@session["capability"]}"
70
- }
71
- }
72
- end
73
-
74
- define_request(:password_reset) do |email|
75
- {
76
- :method => :post,
77
- :url => @description["resources"]["accounts"]["url"],
78
- :body => ""
79
- }
80
- end
81
-
82
- define_request(:delete_account) do
83
- {
84
- :method => :delete,
85
- :url => @resources["account"]["url"],
86
- :headers => {
87
- "Accept" => mediaType("account"),"Content-Type" => mediaType("account"),
88
- "Authorization" =>
89
- "Capability #{@resources["account"]["capability"]}"
90
- }
91
- }
92
- end
93
-
94
- define_request(:update_account) do |info|
95
- {
96
- :method => :put,
97
- :url => @resources["account"]["url"],
98
- :body => info.to_json,
99
- :headers => {
100
- "Accept" => mediaType("account"),"Content-Type" => mediaType("account"),
101
- "Authorization" => "Capability #{@resources["account"]["capability"]}"
102
- }
103
- }
104
- end
105
-
106
- define_request(:create_channel) do |name|
107
- {
108
- :method => :post,
109
- :url => @resources["channels"]["url"],
110
- :body => { :name => name }.to_json,
111
- :headers => {
112
- "Authorization" =>
113
- "Capability #{@resources["channels"]["capability"]}",
114
- "Accept" => mediaType("channel"),
115
- "Content-Type" => mediaType("channel")
116
- }
117
- }
118
- end
119
-
120
- define_request(:channels) do
121
- {
122
- :method => :get,
123
- :url => @resources["channels"]["url"],
124
- :headers => {
125
- "Authorization" =>
126
- "Capability #{@resources["channels"]["capability"]}",
127
- "Accept" => mediaType("channels"),
128
- }
129
- }
130
- end
131
-
132
- define_request(:subscribe) do |subscription_name, channels|
133
- {
134
- :method => :post,
135
- :url => @resources["subscriptions"]["url"],
136
- :body => {
137
- :channels => channels.flatten.map { |name| self[name].url },
138
- :name => subscription_name
139
- }.to_json,
140
- :headers => {
141
- "Authorization" => "Capability #{@resources["subscriptions"]["capability"]}",
142
- "Accept" => mediaType("subscription"),
143
- "Content-Type" => mediaType("subscription")
144
- }
145
- }
146
- end
147
-
148
- define_request(:billing) do
149
- {
150
- :method => :get,
151
- :url => @description["resources"]["billing"]["url"],
152
- :headers => {
153
- "Accept" => "application/json"
154
- }
155
- }
156
- end
157
-
158
- define_request(:billing_subscription) do |info|
159
- {
160
- :method => :put,
161
- :url => @resources["account"]["billing"]["url"],
162
- :body => info.to_json,
163
- :headers => {
164
- "Accept" => mediaType("account"),"Content-Type" => mediaType("account"),
165
- "Authorization" => "Capability #{@resources["account"]["billing"]["capability"]}"
166
- }
167
- }
168
- end
169
-
170
- define_request(:billing_invoices) do
171
- {
172
- :method => :get,
173
- :url => @resources["account"]["billing"]["invoices"]["url"],
174
- :headers => {
175
- "Accept" => "application/json",
176
- "Authorization" => "Capability #{@resources["account"]["billing"]["invoices"]["capability"]}"
177
- }
178
- }
179
- end
180
-
181
- define_request(:billing_invoices_upcoming) do
182
- {
183
- :method => :get,
184
- :url => @resources["account"]["billing"]["invoices"]["upcoming"]["url"],
185
- :headers => {
186
- "Accept" => "application/json",
187
- "Authorization" => "Capability #{@resources["account"]["billing"]["invoices"]["upcoming"]["capability"]}"
188
- }
189
- }
190
- end
191
-
192
- attr_accessor :client, :channels, :session, :resources
14
+ attr_accessor :api, :session, :resources
193
15
 
194
16
  def initialize(url="https://api.spire.io")
195
- @client = Excon
17
+ @api = Spire::API.new(url)
196
18
  @url = url
197
19
  @channels = {}
198
20
  @subscriptions = {}
199
21
  @channel_error_counts = {}
200
22
  @subscription_error_counts = {}
201
- # @headers = { "User-Agent" => "Ruby spire.io client" }
202
- # @timeout = 1
203
23
  discover
204
24
  end
205
25
 
@@ -212,25 +32,18 @@ class Spire
212
32
  end
213
33
 
214
34
  def discover
215
- response = request(:discover)
216
- raise "Error during discovery: #{response.status}" if response.status != 200
217
- @description = JSON.parse(response.body)
218
- #pp @description["schema"]["1.0"]
35
+ @api.discover
219
36
  self
220
37
  end
221
38
 
222
39
  def start(key)
223
- response = request(:start, key)
224
- raise "Error starting a key-based session" if response.status != 201
225
- cache_session(JSON.parse(response.body))
40
+ @session = @api.create_session(key)
226
41
  self
227
42
  end
228
43
 
229
44
  # Authenticates a session using a login and password
230
45
  def login(login, password)
231
- response = request(:login, login, password)
232
- raise "Error attemping to login: (#{response.status}) #{response.body}" if response.status != 201
233
- cache_session(JSON.parse(response.body))
46
+ @session = @api.login(login, password)
234
47
  self
235
48
  end
236
49
 
@@ -239,12 +52,14 @@ class Spire
239
52
  # @param [String] :password Password of new account
240
53
  # @param [String] :password_confirmation Password confirmation (optional)
241
54
  def register(info)
242
- response = request(:register, info)
243
- raise "Error attempting to register: (#{response.status}) #{response.body}" if response.status != 201
244
- cache_session(JSON.parse(response.body))
55
+ @session = @api.create_account(info)
245
56
  self
246
57
  end
247
58
 
59
+ def key
60
+ @session.resources["account"]["key"]
61
+ end
62
+
248
63
  def password_reset_request(email)
249
64
  response = request(:password_reset)
250
65
  unless response.status == 202
@@ -256,15 +71,16 @@ class Spire
256
71
 
257
72
  # Deletes the currently authenticated account
258
73
  def delete_account
259
- request(:delete_account)
74
+ @session.account.delete
260
75
  end
261
76
 
262
77
  # Updates the current account with the new account information
263
78
  # See Spire docs for available settings
264
79
  def update(info)
265
- response = request(:update_account, info)
266
- raise "Error attempting to update account: (#{response.status}) #{response.body}" if response.status != 200
267
- @resources["account"] = JSON.parse(response.body)
80
+ @session.account.update(info)
81
+ #response = request(:update_account, info)
82
+ #raise "Error attempting to update account: (#{response.status}) #{response.body}" if response.status != 200
83
+ #@resources["account"] = JSON.parse(response.body)
268
84
  self
269
85
  end
270
86
 
@@ -308,152 +124,120 @@ class Spire
308
124
  # @param [String] name Name of channel returned
309
125
  # @return [Channel]
310
126
  def [](name)
311
- return @channels[name] if @channels[name]
312
- create_channel(name)
127
+ Channel.new(self, channels[name] || find_or_create_channel(name))
128
+ end
129
+
130
+ def channels
131
+ @session.channels
313
132
  end
314
133
 
315
134
  # Creates a channel on spire. Returns a Channel object. Note that this will
316
135
  # fail with a 409 if a channel with the same name exists.
317
- def create_channel(name)
136
+ def find_or_create_channel(name)
318
137
  @channel_error_counts[name] ||= 0
319
- response = request(:create_channel, name)
320
- return find_existing_channel(name) if response.status == 409 and @channel_error_counts[name] < RETRY_CREATION_LIMIT
321
- if !(response.status == 201 || response.status == 200)
322
- raise "Error creating or accessing a channel: (#{response.status}) #{response.body}"
138
+
139
+ begin
140
+ return @session.create_channel(name)
141
+ # TODO custom error class for Conflict, which we can
142
+ # then match here, instead of testing for error message
143
+ rescue => error
144
+ if error.message =~ /409/
145
+
146
+ # Dear retry, I love you. Affectionately, Matthew.
147
+ if channel = @session.channels![name]
148
+ return channel
149
+ else
150
+ @channel_error_counts[name] += 1
151
+ retry unless @channel_error_counts >= RETRY_CREATION_LIMIT
152
+ end
153
+
154
+ else
155
+ raise error
156
+ end
323
157
  end
324
- new_channel = Channel.new(self,JSON.parse(response.body))
325
- @channels[name] = new_channel
326
- new_channel
327
158
  end
328
159
 
329
- def find_existing_channel(name)
330
- @channel_error_counts[name] += 1
331
- retrieve_session
332
- self[name]
333
- end
334
-
335
160
  # Returns a subscription object for the given channels
336
161
  # @param [String] subscription_name Name for the subscription
337
162
  # @param [String] channels One or more channel names for the subscription to listen on
338
163
  # @return [Subscription]
339
- def subscribe(subscription_name, *channels)
164
+ def subscribe(name, *channels)
165
+ channels.each { |channel| self.find_or_create_channel(channel) }
166
+ Subscription.new(
167
+ @session.subscriptions[name] || find_or_create_subscription(name, *channels)
168
+ )
169
+ end
170
+
171
+ def find_or_create_subscription(subscription_name, *channels)
340
172
  @subscription_error_counts[subscription_name] ||= 0
341
- return @subscriptions[subscription_name] if subscription_name and @subscriptions[subscription_name]
342
- response = request(:subscribe, subscription_name, channels)
343
- return find_existing_subscription(subscription_name, channels) if response.status == 409 and
344
- @subscription_error_counts[subscription_name] < RETRY_CREATION_LIMIT
345
- raise "Error creating a subscription: (#{response.status}) #{response.body}" if !(response.status == 201 || response.status == 200)
346
- s = Subscription.new(self,JSON.parse(response.body))
347
- @subscriptions[s.name] = s
348
- s
173
+ begin
174
+ return @session.create_subscription(subscription_name, channels)
175
+ rescue => error
176
+ if error.message =~ /409/
177
+
178
+ if subscription = @session.subscriptions![subscription_name]
179
+ return subscription
180
+ else
181
+ retry unless @subscription_error_counts >= RETRY_CREATION_LIMIT
182
+ end
183
+
184
+ else
185
+ raise error
186
+ end
187
+ end
349
188
  end
189
+
350
190
  alias :subscription :subscribe #For compatibility with other clients
351
191
 
352
- def find_existing_subscription(name, channels)
353
- @subscription_error_counts[name] += 1
354
- retrieve_session
355
- self.subscribe(name, *channels)
192
+ #Returns an array of subscription objects for all of this account's subscriptions
193
+ #@return [Array]
194
+ def subscriptions
195
+ @session.subscriptions.values
356
196
  end
357
197
 
358
198
  # Returns a billing object than contains a list of all the plans available
359
199
  # @param [String] info optional object description
360
200
  # @return [Billing]
361
- def billing(info=nil)
362
- response = request(:billing)
363
- raise "Error getting billing plans: #{response.status}" if response.status != 200
364
- Billing.new(self,JSON.parse(response.body))
201
+ def billing
202
+ @api.billing
365
203
  end
366
204
 
367
205
  # Updates and subscribe the account to a billing plan
368
206
  # @param [Object] info data containing billing description
369
207
  # @return [Account]
370
208
  def billing_subscription(info)
371
- response = request(:billing_subscription)
372
- raise "Error attempting to update account billing: (#{response.status}) #{response.body}" if response.status != 200
373
- @resources["account"] = JSON.parse(response.body)
374
- self
209
+ @session.account.billing_subscription(info)
210
+ #response = request(:billing_subscription)
211
+ #raise "Error attempting to update account billing: (#{response.status}) #{response.body}" if response.status != 200
212
+ #@resources["account"] = JSON.parse(response.body)
213
+ #self
375
214
  end
376
215
 
377
-
216
+
378
217
  # Object representing a Spire channel
379
218
  #
380
219
  # You can get a channel object by calling [] on a Spire object
381
220
  # * spire = Spire.new
382
221
  # * spire.start("your api key")
383
222
  # * channel = spire["channel name"]
384
- class Channel
385
- include Requestable
386
-
387
- define_request(:publish) do |body|
388
- {
389
- :method => :post,
390
- :url => url,
391
- :body => body,
392
- :headers => {
393
- "Authorization" => "Capability #{@properties["capability"]}",
394
- "Accept" => mediaType("message"),
395
- "Content-Type" => mediaType("message")
396
- }
397
- }
398
- end
399
-
400
- define_request(:delete) do
401
- {
402
- :method => :delete,
403
- :url => url,
404
- :headers => {
405
- "Authorization" => "Capability #{capability}"
406
- }
407
- }
408
- end
409
-
410
- def initialize(spire, properties)
223
+ class Channel < SimpleDelegator
224
+ def initialize(spire, channel)
225
+ super(channel)
411
226
  @spire = spire
412
- @client = spire.client
413
- @properties = properties
414
- end
415
-
416
- def url
417
- @properties["url"]
418
- end
419
-
420
- def key
421
- @properties["key"]
422
- end
423
-
424
- def name
425
- @properties["name"]
426
- end
427
-
428
- def capability
429
- @properties["capability"]
430
- end
431
-
432
- def delete
433
- response = request(:delete)
434
- raise "Error deleting a channel" if response.status != 204
435
227
  end
436
-
437
228
  # Obtain a subscription for the channel
438
229
  # @param [String] subscription_name Name of the subscription
439
230
  # @return [Subscription]
440
231
  def subscribe(subscription_name = nil)
441
- @spire.subscribe(subscription_name, self.name)
442
- end
443
-
444
- #Publishes a message to the channel
445
- # @param [String] message Message to be posted
446
- # @return [Hash] response from the server
447
- def publish(message)
448
- response = request(:publish, {:content => message}.to_json)
449
- raise "Error publishing a message: (#{response.status}) #{response.body}" if response.status != 201
450
- JSON.parse(response.body)
232
+ @spire.subscribe(subscription_name, properties["name"])
451
233
  end
452
234
 
453
- def mediaType(name)
454
- @spire.mediaType(name)
235
+ # this is required because Delegator's method_missing relies
236
+ # on the object having a method defined, but in this case
237
+ # the API::Channel is also using method_missing
238
+ def name
239
+ __getobj__.name
455
240
  end
456
-
457
241
  end
458
242
 
459
243
  # The subscription class represents a read connection to a Spire channel
@@ -468,214 +252,94 @@ class Spire
468
252
  # *OR*
469
253
  # * channel = spire["channel name"]
470
254
  # * subscription = channel.subscribe("subscription name")
471
- class Subscription
472
- include Requestable
473
-
474
- define_request(:listen) do |options|
475
- timeout = options[:timeout]||30
476
- delay = options[:delay]||0
477
- order_by = options[:order_by]||'desc'
478
- {
479
- :method => :get,
480
- :url => @properties["url"],
481
- :query => {
482
- "timeout" => timeout,
483
- "last-message" => @last||'0',
484
- "order-by" => order_by,
485
- "delay" => delay
486
- },
487
- :headers => {
488
- "Authorization" => "Capability #{@properties["capability"]}",
489
- "Accept" => mediaType("events")
490
- }
491
- }
492
- end
493
-
494
- define_request(:delete) do
495
- {
496
- :method => :delete,
497
- :url => url,
498
- :headers => {
499
- "Authorization" => "Capability #{capability}"
500
- }
501
- }
502
- end
503
-
504
- attr_accessor :messages, :last
505
-
506
- def initialize(spire,properties)
507
- @spire = spire
508
- @client = spire.client
509
- @properties = properties
510
- @messages = []
511
- @listening_thread = nil
512
- @listeners = {}
513
- @listening_threads = {}
514
- @listener_mutex = Mutex.new
515
- @listener_thread_mutex = Mutex.new
516
- end
517
-
518
- def key
519
- @properties["key"]
520
- end
255
+ class Subscription < SimpleDelegator
521
256
 
257
+ # this is required because Delegator's method_missing relies
258
+ # on the object having a method defined, but in this case
259
+ # the API::Subscription is also using method_missing
522
260
  def name
523
- @properties["name"]
524
- end
525
-
526
- def capability
527
- @properties["capability"]
261
+ __getobj__.name
528
262
  end
529
263
 
530
- def url
531
- @properties["url"]
532
- end
533
-
534
- def delete
535
- response = request(:delete)
536
- raise "Error deleting a subscription" if response.status != 204
264
+ # misnamed method, here for backompat. Should be something like #get_messages,
265
+ # because it only makes one request.
266
+ def listen(options={})
267
+ long_poll(options).map {|message| message["content"] }
537
268
  end
538
269
 
539
- # Adds a listener (ruby block) to be called each time a message is received on the channel
540
- #
541
- # You must call #start_listening to actually start listening for messages
542
- # @note Listeners are executed in their own thread, so practice proper thread safety!
543
- # @param [String] name Name for the listener. One will be generated if not provided
544
- # @return [String] Name of the listener
545
- def add_listener(listener_name = nil, &block)
546
- @listener_mutex.synchronize do
547
- while !listener_name
548
- new_name = "Listener-#{rand(9999999)}"
549
- listener_name = new_name unless @listeners.has_key?(new_name)
550
- end
551
- @listeners[listener_name] = block
552
- end
553
- listener_name
270
+ # wraps the underlying Subscription#add_listener to
271
+ # provided named listeners, threading, and a
272
+ # stop_listening method.
273
+ def add_listener(name=nil, &block)
274
+ raise ArgumentError unless block_given?
275
+ name ||= generate_listener_name
276
+ listener = wrap_listener(&block)
277
+ listeners[name] = listener
278
+ __getobj__.add_listener(&listener)
554
279
  end
555
280
 
556
- # Removes a listener by name
557
- #
558
- # @param [String] name Name of the listener to remove
559
- # @param [Boolean] kill_current_threads Kill any currently running threads of the removed listener
560
- # @return [Proc] Listener that was removed
561
- def remove_listener(name, kill_current_threads = true)
562
- l = nil #scope
563
- @listener_mutex.synchronize do
564
- l = @listeners.delete(name)
281
+ def remove_listener(listener)
282
+ if listener.is_a? String
283
+ listener = listeners[listener]
565
284
  end
566
- kill_listening_threads(name) if kill_current_threads
567
- l
285
+ __getobj__.listeners.delete(listener)
568
286
  end
569
287
 
570
- # Removes all current listeners
571
- # @param [Boolean] kill_current_threads Kill any currently running threads of the removed listener.
572
- def remove_all_listeners(kill_current_threads = true)
573
- @listener_mutex.synchronize do
574
- @listeners = {}
288
+ def wrap_listener(&block)
289
+ lambda do |message|
290
+ Thread.new do
291
+ # Messages received after a call to stop_listening
292
+ # will not be processed.
293
+ yield message["content"] if @listening
294
+ end
575
295
  end
576
- kill_listening_threads if kill_current_threads
577
- true
578
296
  end
579
297
 
580
- # Starts the listening thread. This must be called to enable any listeners you have added.
581
- #
582
- # You can continue to add more listeners after starting the listening process
583
- # @note Will raise an exception if listening has already been started
584
- def start_listening
585
- raise "Already listening" if @listening_thread
586
- @listening_thread = Thread.new {
587
- while true
588
- new_messages = self.listen
589
- next unless new_messages.size > 0
590
- current_listeners.each do |name, listener|
591
- new_messages.each do |m|
592
- thread = Thread.new {
593
- begin
594
- listener.call(m)
595
- rescue
596
- puts "Error while running listener #{name}: #{$!.inspect}"
597
- puts $!.backtrace.join("\n")
598
- end
599
- }
600
- @listener_thread_mutex.synchronize do
601
- @listening_threads[name] ||= []
602
- @listening_threads[name] << thread
603
- end
604
- end
605
- end
606
- end
607
- }
298
+ def listeners
299
+ @listeners ||= {}
608
300
  end
609
301
 
610
- # Stops the listening process
611
- # @param [Boolean] kill_current_threads Kills any currently running listener threads
612
- def stop_listening(kill_current_threads = true)
613
- @listener_thread_mutex.synchronize do
614
- @listening_thread.kill if @listening_thread
615
- @listening_thread = nil
616
- end
617
- kill_listening_threads if kill_current_threads
618
- end
619
-
620
- # Kills any currently executing listeners
621
- # @param [String] name_to_kill Kill only currently executing listeners that have this name
622
- def kill_listening_threads(name_to_kill = nil)
623
- @listener_thread_mutex.synchronize do
624
- @listening_threads.each do |name, threads|
625
- next if name_to_kill and name_to_kill != name
626
- threads.each {|t| t.kill }
627
- @listening_threads[name] = []
628
- end
302
+ def generate_listener_name
303
+ listener_name = nil
304
+ while !listener_name
305
+ new_name = "Listener-#{rand(9999999)}"
306
+ listener_name = new_name unless listeners.has_key?(new_name)
629
307
  end
308
+ listener_name
630
309
  end
631
310
 
632
- # Listen (and block) for any new incoming messages.
633
- # @params [Hash] A hash of containing:
634
- # [Integer] timeout Max time to wait for a new message before returning
635
- # [String] order_by Either "desc" or "asc"
636
- # @return [Array] An array of messages received
637
- def listen(options={})
638
- response = request(:listen, options)
639
- raise "Error listening for messages: (#{response.status}) #{response.body}" if response.status != 200
640
- new_messages = JSON.parse(response.body)["messages"]
641
- @listener_mutex.synchronize do
642
- @last = new_messages.last["timestamp"] unless new_messages.empty?
643
- new_messages.map! { |m| m["content"] }
644
- @messages += new_messages
311
+ def start_listening(options={})
312
+ @listening = true
313
+ Thread.new do
314
+ long_poll(options) while @listening
645
315
  end
646
- new_messages
647
316
  end
648
317
 
649
- def mediaType(name)
650
- @spire.mediaType(name)
318
+ def stop_listening
319
+ @listening = false
651
320
  end
652
321
 
653
- private
654
- def current_listeners
655
- @listener_mutex.synchronize do #To prevent synch problems adding a new listener while looping
656
- @listeners.dup
657
- end
658
- end
659
322
  end
660
323
 
661
- # Object representing a Spire billing
662
- #
663
- # You can get all the billing plans by calling the method billing in Spire object
664
- # * spire = Spire.new
665
- # * billing = spire.billing()
666
- # * plans = billing.plans
667
- class Billing
668
- def initialize(spire,properties)
669
- @spire = spire
670
- @properties = properties
671
- end
324
+
325
+ ## Object representing a Spire billing
326
+ ##
327
+ ## You can get all the billing plans by calling the method billing in Spire object
328
+ ## * spire = Spire.new
329
+ ## * billing = spire.billing()
330
+ ## * plans = billing.plans
331
+ #class Billing
332
+ #def initialize(spire,properties)
333
+ #@spire = spire
334
+ #@properties = properties
335
+ #end
672
336
 
673
- def url
674
- @properties["url"]
675
- end
337
+ #def url
338
+ #@properties["url"]
339
+ #end
676
340
 
677
- def plans
678
- @properties["plans"]
679
- end
680
- end
341
+ #def plans
342
+ #@properties["plans"]
343
+ #end
344
+ #end
681
345
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spire_io
3
3
  version: !ruby/object:Gem::Version
4
- hash: -3702664328
4
+ hash: -3702664330
5
5
  prerelease: true
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
9
  - 0
10
10
  - alpha
11
- - 2
12
- version: 1.0.0.alpha.2
11
+ - 5
12
+ version: 1.0.0.alpha.5
13
13
  platform: ruby
14
14
  authors:
15
15
  - Dan Yoder
@@ -18,7 +18,7 @@ autorequire:
18
18
  bindir: bin
19
19
  cert_chain: []
20
20
 
21
- date: 2012-01-23 00:00:00 -08:00
21
+ date: 2012-01-27 00:00:00 -08:00
22
22
  default_executable:
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency
@@ -93,7 +93,6 @@ extensions: []
93
93
  extra_rdoc_files: []
94
94
 
95
95
  files:
96
- - lib/requestable.rb
97
96
  - lib/spire_io.rb
98
97
  has_rdoc: true
99
98
  homepage: https://github.com/spire-io/spire.io.rb
data/lib/requestable.rb DELETED
@@ -1,70 +0,0 @@
1
- module Requestable
2
-
3
- def self.included(mod)
4
- mod.module_eval do
5
- extend(ClassMethods)
6
- include(InstanceMethods)
7
- end
8
- end
9
-
10
- module ClassMethods
11
- def requests
12
- @requests ||= {}
13
- end
14
-
15
- def define_request(name, &block)
16
- requests[name] = block
17
- end
18
- end
19
-
20
- module InstanceMethods
21
- def prepare_request(name, *args)
22
- if block = self.class.requests[name]
23
- options = self.instance_exec(*args, &block)
24
- Request.new(@client, options)
25
- else
26
- raise ArgumentError, "No request has been defined for #{name.inspect}"
27
- end
28
- end
29
-
30
- def request(name, *args)
31
- prepare_request(name, *args).exec
32
- end
33
- end
34
-
35
- class Request
36
- attr_accessor :url
37
- def initialize(client, options)
38
- @client = client
39
- @method = options.delete(:method)
40
- @url = options.delete(:url)
41
- @options = options
42
- @options[:headers] = {
43
- "User-Agent" => "Ruby spire.io client"
44
- }.merge(@options[:headers])
45
- end
46
-
47
- def headers
48
- @options[:headers]
49
- end
50
-
51
- def body
52
- @options[:body]
53
- end
54
-
55
- def body=(val)
56
- @options[:body] = val
57
- end
58
-
59
- def query
60
- @options[:query]
61
- end
62
-
63
- def exec
64
- @client.send(@method, @url, @options)
65
- end
66
- end
67
-
68
- end
69
-
70
-