ibm_sbdtc_rest 0.0.0

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.
@@ -0,0 +1,48 @@
1
+ require 'ibm_cloud_rest/core/adapters/restclient'
2
+
3
+ # Abstraction layet for HTTP communications.
4
+ #
5
+ # By defining a basic API that IbmCloudRest is relying on,
6
+ # it allows for easy experimentations and implementations of various libraries.
7
+ #
8
+ # Most of the API is based on the RestClient API that was used in the early version of IbmCloudRest.
9
+ #
10
+ module HttpAbstraction
11
+
12
+ # here is the list of exception expected by IbmCloudRest
13
+ # please convert the underlying errors in this set of known
14
+ # exceptions.
15
+ class ResourceNotFound < StandardError; end
16
+ class RequestFailed < StandardError; end
17
+ class RequestTimeout < StandardError; end
18
+ class ServerBrokeConnection < StandardError; end
19
+ class Conflict < StandardError; end
20
+
21
+
22
+ # # Here is the API you need to implement if you want to write a new adapter
23
+ # # See adapters/restclient.rb for more information.
24
+ #
25
+ # def self.proxy=(url)
26
+ # end
27
+ #
28
+ # def self.proxy
29
+ # end
30
+ #
31
+ # def self.get(uri, headers=nil)
32
+ # end
33
+ #
34
+ # def self.post(uri, payload, headers=nil)
35
+ # end
36
+ #
37
+ # def self.put(uri, payload, headers=nil)
38
+ # end
39
+ #
40
+ # def self.delete(uri, headers=nil)
41
+ # end
42
+ #
43
+ # def self.copy(uri, headers)
44
+ # end
45
+
46
+ end
47
+
48
+ HttpAbstraction.extend(RestClientAdapter::API)
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,49 @@
1
+ module RestAPI
2
+
3
+ def put(uri, doc = nil)
4
+ payload = doc.to_json if doc
5
+ begin
6
+ JSON.parse(HttpAbstraction.put(uri, payload))
7
+ rescue Exception => e
8
+ if $DEBUG
9
+ raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}"
10
+ else
11
+ raise e
12
+ end
13
+ end
14
+ end
15
+
16
+ def get(uri)
17
+ begin
18
+ JSON.parse(HttpAbstraction.get(uri), :max_nesting => false)
19
+ rescue => e
20
+ if $DEBUG
21
+ raise "Error while sending a GET request #{uri}\n: #{e}"
22
+ else
23
+ raise e
24
+ end
25
+ end
26
+ end
27
+
28
+ def post(uri, doc = nil)
29
+ payload = doc.to_json if doc
30
+ begin
31
+ JSON.parse(HttpAbstraction.post(uri, payload))
32
+ rescue Exception => e
33
+ if $DEBUG
34
+ raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}"
35
+ else
36
+ raise e
37
+ end
38
+ end
39
+ end
40
+
41
+ def delete(uri)
42
+ JSON.parse(HttpAbstraction.delete(uri))
43
+ end
44
+
45
+ def copy(uri, destination)
46
+ JSON.parse(HttpAbstraction.copy(uri, {'Destination' => destination}))
47
+ end
48
+
49
+ end
@@ -0,0 +1,88 @@
1
+ module IbmCloudRest
2
+ class Server
3
+ attr_accessor :uri, :uuid_batch_count, :available_instances
4
+ def initialize(server = 'https://www.ibm.com', base_path= '/cloud/developer/api/rest/20090403', uuid_batch_count = 1000)
5
+ @uri = server+base_path
6
+ @uuid_batch_count = uuid_batch_count
7
+ end
8
+
9
+ # Lists all "available" instances.
10
+ # An available instance, is a instance that was specified
11
+ # as avaiable by your code.
12
+ # It allows to define common instances to use and reuse in your code
13
+ def available_instances
14
+ @available_instances ||= {}
15
+ end
16
+
17
+ # Adds a new available instance and create it unless it already exists
18
+ #
19
+ # Example:
20
+ #
21
+ # @couch = IbmCloudRest::Server.new
22
+ # @couch.define_available_instance(:default, "tech-blog")
23
+ #
24
+ def define_available_instance(reference, db_name, create_unless_exists = true)
25
+ available_instances[reference.to_sym] = create_unless_exists ? instance!(db_name) : instance(db_name)
26
+ end
27
+
28
+ # Checks that a instance is set as available
29
+ #
30
+ # Example:
31
+ #
32
+ # @couch.available_instance?(:default)
33
+ #
34
+ def available_instance?(ref_or_name)
35
+ ref_or_name.is_a?(Symbol) ? available_instances.keys.include?(ref_or_name) : available_instances.values.map{|db| db.name}.include?(ref_or_name)
36
+ end
37
+
38
+ def default_instance=(name, create_unless_exists = true)
39
+ define_available_instance(:default, name, create_unless_exists = true)
40
+ end
41
+
42
+ def default_instance
43
+ available_instances[:default]
44
+ end
45
+
46
+ # Lists all instances on the server
47
+ def instances
48
+ IbmCloudRest.get "#{@uri}/instances"
49
+ end
50
+
51
+ # Returns a IbmCloudRest::instance for the given name
52
+ def instance(name)
53
+ IbmCloudRest::instance.new(self, name)
54
+ end
55
+
56
+ # Creates the instance if it doesn't exist
57
+ def instance!(name)
58
+ create_db(name) rescue nil
59
+ instance(name)
60
+ end
61
+
62
+ # GET the welcome message
63
+ def info
64
+ IbmCloudRest.get "#{@uri}/"
65
+ end
66
+
67
+ # Create a instance
68
+ def create_db(name)
69
+ IbmCloudRest.put "#{@uri}/#{name}"
70
+ instance(name)
71
+ end
72
+
73
+ # Restart the CouchDB instance
74
+ def restart!
75
+ IbmCloudRest.post "#{@uri}/_restart"
76
+ end
77
+
78
+ # Retrive an unused UUID from CouchDB. Server instances manage caching a list of unused UUIDs.
79
+ def next_uuid(count = @uuid_batch_count)
80
+ @uuids ||= []
81
+ if @uuids.empty?
82
+ @uuids = IbmCloudRest.get("#{@uri}/_uuids?count=#{count}")["uuids"]
83
+ end
84
+ @uuids.pop
85
+ end
86
+
87
+ end
88
+ end
File without changes
@@ -0,0 +1,3 @@
1
+ mixins_dir = File.join(File.dirname(__FILE__), 'mixins')
2
+
3
+ require File.join(mixins_dir, 'callbacks')
@@ -0,0 +1,483 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'support', 'class')
2
+
3
+ # Extracted from ActiveSupport::Callbacks written by Yehuda Katz
4
+ # http://github.com/wycats/rails/raw/abstract_controller/activesupport/lib/active_support/new_callbacks.rb
5
+ # http://github.com/wycats/rails/raw/18b405f154868204a8f332888871041a7bad95e1/activesupport/lib/active_support/callbacks.rb
6
+
7
+ module IbmCloudRest
8
+ # Callbacks are hooks into the lifecycle of an object that allow you to trigger logic
9
+ # before or after an alteration of the object state.
10
+ #
11
+ # Mixing in this module allows you to define callbacks in your class.
12
+ #
13
+ # Example:
14
+ # class Storage
15
+ # include ActiveSupport::Callbacks
16
+ #
17
+ # define_callbacks :save
18
+ # end
19
+ #
20
+ # class ConfigStorage < Storage
21
+ # save_callback :before, :saving_message
22
+ # def saving_message
23
+ # puts "saving..."
24
+ # end
25
+ #
26
+ # save_callback :after do |object|
27
+ # puts "saved"
28
+ # end
29
+ #
30
+ # def save
31
+ # _run_save_callbacks do
32
+ # puts "- save"
33
+ # end
34
+ # end
35
+ # end
36
+ #
37
+ # config = ConfigStorage.new
38
+ # config.save
39
+ #
40
+ # Output:
41
+ # saving...
42
+ # - save
43
+ # saved
44
+ #
45
+ # Callbacks from parent classes are inherited.
46
+ #
47
+ # Example:
48
+ # class Storage
49
+ # include ActiveSupport::Callbacks
50
+ #
51
+ # define_callbacks :save
52
+ #
53
+ # save_callback :before, :prepare
54
+ # def prepare
55
+ # puts "preparing save"
56
+ # end
57
+ # end
58
+ #
59
+ # class ConfigStorage < Storage
60
+ # save_callback :before, :saving_message
61
+ # def saving_message
62
+ # puts "saving..."
63
+ # end
64
+ #
65
+ # save_callback :after do |object|
66
+ # puts "saved"
67
+ # end
68
+ #
69
+ # def save
70
+ # _run_save_callbacks do
71
+ # puts "- save"
72
+ # end
73
+ # end
74
+ # end
75
+ #
76
+ # config = ConfigStorage.new
77
+ # config.save
78
+ #
79
+ # Output:
80
+ # preparing save
81
+ # saving...
82
+ # - save
83
+ # saved
84
+ module Callbacks
85
+ def self.included(klass)
86
+ klass.extend ClassMethods
87
+ end
88
+
89
+ def run_callbacks(kind, options = {}, &blk)
90
+ send("_run_#{kind}_callbacks", &blk)
91
+ end
92
+
93
+ class Callback
94
+ @@_callback_sequence = 0
95
+
96
+ attr_accessor :filter, :kind, :name, :options, :per_key, :klass
97
+ def initialize(filter, kind, options, klass, name)
98
+ @kind, @klass = kind, klass
99
+ @name = name
100
+
101
+ normalize_options!(options)
102
+
103
+ @per_key = options.delete(:per_key)
104
+ @raw_filter, @options = filter, options
105
+ @filter = _compile_filter(filter)
106
+ @compiled_options = _compile_options(options)
107
+ @callback_id = next_id
108
+
109
+ _compile_per_key_options
110
+ end
111
+
112
+ def clone(klass)
113
+ obj = super()
114
+ obj.klass = klass
115
+ obj.per_key = @per_key.dup
116
+ obj.options = @options.dup
117
+ obj.per_key[:if] = @per_key[:if].dup
118
+ obj.per_key[:unless] = @per_key[:unless].dup
119
+ obj.options[:if] = @options[:if].dup
120
+ obj.options[:unless] = @options[:unless].dup
121
+ obj
122
+ end
123
+
124
+ def normalize_options!(options)
125
+ options[:if] = Array(options[:if])
126
+ options[:unless] = Array(options[:unless])
127
+
128
+ options[:per_key] ||= {}
129
+ options[:per_key][:if] = Array(options[:per_key][:if])
130
+ options[:per_key][:unless] = Array(options[:per_key][:unless])
131
+ end
132
+
133
+ def next_id
134
+ @@_callback_sequence += 1
135
+ end
136
+
137
+ def matches?(_kind, _name, _filter)
138
+ @kind == _kind &&
139
+ @name == _name &&
140
+ @filter == _filter
141
+ end
142
+
143
+ def _update_filter(filter_options, new_options)
144
+ filter_options[:if].push(new_options[:unless]) if new_options.key?(:unless)
145
+ filter_options[:unless].push(new_options[:if]) if new_options.key?(:if)
146
+ end
147
+
148
+ def recompile!(_options, _per_key)
149
+ _update_filter(self.options, _options)
150
+ _update_filter(self.per_key, _per_key)
151
+
152
+ @callback_id = next_id
153
+ @filter = _compile_filter(@raw_filter)
154
+ @compiled_options = _compile_options(@options)
155
+ _compile_per_key_options
156
+ end
157
+
158
+ def _compile_per_key_options
159
+ key_options = _compile_options(@per_key)
160
+
161
+ @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
162
+ def _one_time_conditions_valid_#{@callback_id}?
163
+ true #{key_options[0]}
164
+ end
165
+ RUBY_EVAL
166
+ end
167
+
168
+ # This will supply contents for before and around filters, and no
169
+ # contents for after filters (for the forward pass).
170
+ def start(key = nil, options = {})
171
+ object, terminator = (options || {}).values_at(:object, :terminator)
172
+
173
+ return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?")
174
+
175
+ terminator ||= false
176
+
177
+ # options[0] is the compiled form of supplied conditions
178
+ # options[1] is the "end" for the conditional
179
+
180
+ if @kind == :before || @kind == :around
181
+ if @kind == :before
182
+ # if condition # before_save :filter_name, :if => :condition
183
+ # filter_name
184
+ # end
185
+ filter = <<-RUBY_EVAL
186
+ unless halted
187
+ result = #{@filter}
188
+ halted ||= (#{terminator})
189
+ end
190
+ RUBY_EVAL
191
+ [@compiled_options[0], filter, @compiled_options[1]].compact.join("\n")
192
+ else
193
+ # Compile around filters with conditions into proxy methods
194
+ # that contain the conditions.
195
+ #
196
+ # For `around_save :filter_name, :if => :condition':
197
+ #
198
+ # def _conditional_callback_save_17
199
+ # if condition
200
+ # filter_name do
201
+ # yield self
202
+ # end
203
+ # else
204
+ # yield self
205
+ # end
206
+ # end
207
+
208
+ name = "_conditional_callback_#{@kind}_#{next_id}"
209
+ txt = <<-RUBY_EVAL
210
+ def #{name}(halted)
211
+ #{@compiled_options[0] || "if true"} && !halted
212
+ #{@filter} do
213
+ yield self
214
+ end
215
+ else
216
+ yield self
217
+ end
218
+ end
219
+ RUBY_EVAL
220
+ @klass.class_eval(txt)
221
+ "#{name}(halted) do"
222
+ end
223
+ end
224
+ end
225
+
226
+ # This will supply contents for around and after filters, but not
227
+ # before filters (for the backward pass).
228
+ def end(key = nil, options = {})
229
+ object = (options || {})[:object]
230
+
231
+ return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?")
232
+
233
+ if @kind == :around || @kind == :after
234
+ # if condition # after_save :filter_name, :if => :condition
235
+ # filter_name
236
+ # end
237
+ if @kind == :after
238
+ [@compiled_options[0], @filter, @compiled_options[1]].compact.join("\n")
239
+ else
240
+ "end"
241
+ end
242
+ end
243
+ end
244
+
245
+ private
246
+ # Options support the same options as filters themselves (and support
247
+ # symbols, string, procs, and objects), so compile a conditional
248
+ # expression based on the options
249
+ def _compile_options(options)
250
+ return [] if options[:if].empty? && options[:unless].empty?
251
+
252
+ conditions = []
253
+
254
+ unless options[:if].empty?
255
+ conditions << Array(_compile_filter(options[:if]))
256
+ end
257
+
258
+ unless options[:unless].empty?
259
+ conditions << Array(_compile_filter(options[:unless])).map {|f| "!#{f}"}
260
+ end
261
+
262
+ ["if #{conditions.flatten.join(" && ")}", "end"]
263
+ end
264
+
265
+ # Filters support:
266
+ # Arrays:: Used in conditions. This is used to specify
267
+ # multiple conditions. Used internally to
268
+ # merge conditions from skip_* filters
269
+ # Symbols:: A method to call
270
+ # Strings:: Some content to evaluate
271
+ # Procs:: A proc to call with the object
272
+ # Objects:: An object with a before_foo method on it to call
273
+ #
274
+ # All of these objects are compiled into methods and handled
275
+ # the same after this point:
276
+ # Arrays:: Merged together into a single filter
277
+ # Symbols:: Already methods
278
+ # Strings:: class_eval'ed into methods
279
+ # Procs:: define_method'ed into methods
280
+ # Objects::
281
+ # a method is created that calls the before_foo method
282
+ # on the object.
283
+ def _compile_filter(filter)
284
+ method_name = "_callback_#{@kind}_#{next_id}"
285
+ case filter
286
+ when Array
287
+ filter.map {|f| _compile_filter(f)}
288
+ when Symbol
289
+ filter
290
+ when Proc
291
+ @klass.send(:define_method, method_name, &filter)
292
+ method_name << (filter.arity == 1 ? "(self)" : "")
293
+ when String
294
+ @klass.class_eval <<-RUBY_EVAL
295
+ def #{method_name}
296
+ #{filter}
297
+ end
298
+ RUBY_EVAL
299
+ method_name
300
+ else
301
+ kind, name = @kind, @name
302
+ @klass.send(:define_method, method_name) do
303
+ filter.send("#{kind}_#{name}", self)
304
+ end
305
+ method_name
306
+ end
307
+ end
308
+ end
309
+
310
+ # This method_missing is supplied to catch callbacks with keys and create
311
+ # the appropriate callback for future use.
312
+ def method_missing(meth, *args, &blk)
313
+ if meth.to_s =~ /_run__([\w:]+)__(\w+)__(\w+)__callbacks/
314
+ return self.class._create_and_run_keyed_callback($1, $2.to_sym, $3.to_sym, self, &blk)
315
+ end
316
+ super
317
+ end
318
+
319
+ # An Array with a compile method
320
+ class CallbackChain < Array
321
+ def initialize(symbol)
322
+ @symbol = symbol
323
+ end
324
+
325
+ def compile(key = nil, options = {})
326
+ method = []
327
+ method << "halted = false"
328
+ each do |callback|
329
+ method << callback.start(key, options)
330
+ end
331
+ method << "yield self if block_given?"
332
+ reverse_each do |callback|
333
+ method << callback.end(key, options)
334
+ end
335
+ method.compact.join("\n")
336
+ end
337
+
338
+ def clone(klass)
339
+ chain = CallbackChain.new(@symbol)
340
+ chain.push(*map {|c| c.clone(klass)})
341
+ end
342
+ end
343
+
344
+ module ClassMethods
345
+ CHAINS = {:before => :before, :around => :before, :after => :after} unless self.const_defined?("CHAINS")
346
+
347
+ # Make the _run_save_callbacks method. The generated method takes
348
+ # a block that it'll yield to. It'll call the before and around filters
349
+ # in order, yield the block, and then run the after filters.
350
+ #
351
+ # _run_save_callbacks do
352
+ # save
353
+ # end
354
+ #
355
+ # The _run_save_callbacks method can optionally take a key, which
356
+ # will be used to compile an optimized callback method for each
357
+ # key. See #define_callbacks for more information.
358
+ def _define_runner(symbol, str, options)
359
+ str = <<-RUBY_EVAL
360
+ def _run_#{symbol}_callbacks(key = nil)
361
+ if key
362
+ send("_run__\#{self.class.name.split("::").last}__#{symbol}__\#{key}__callbacks") { yield if block_given? }
363
+ else
364
+ #{str}
365
+ end
366
+ end
367
+ RUBY_EVAL
368
+
369
+ class_eval str, __FILE__, __LINE__ + 1
370
+
371
+ before_name, around_name, after_name =
372
+ options.values_at(:before, :after, :around)
373
+ end
374
+
375
+ # This is called the first time a callback is called with a particular
376
+ # key. It creates a new callback method for the key, calculating
377
+ # which callbacks can be omitted because of per_key conditions.
378
+ def _create_and_run_keyed_callback(klass, kind, key, obj, &blk)
379
+ @_keyed_callbacks ||= {}
380
+ @_keyed_callbacks[[kind, key]] ||= begin
381
+ str = self.send("_#{kind}_callbacks").compile(key, :object => obj, :terminator => self.send("_#{kind}_terminator"))
382
+
383
+ self.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
384
+ def _run__#{klass.split("::").last}__#{kind}__#{key}__callbacks
385
+ #{str}
386
+ end
387
+ RUBY_EVAL
388
+
389
+ true
390
+ end
391
+
392
+ obj.send("_run__#{klass.split("::").last}__#{kind}__#{key}__callbacks", &blk)
393
+ end
394
+
395
+ # Define callbacks.
396
+ #
397
+ # Creates a <name>_callback method that you can use to add callbacks.
398
+ #
399
+ # Syntax:
400
+ # save_callback :before, :before_meth
401
+ # save_callback :after, :after_meth, :if => :condition
402
+ # save_callback :around {|r| stuff; yield; stuff }
403
+ #
404
+ # The <name>_callback method also updates the _run_<name>_callbacks
405
+ # method, which is the public API to run the callbacks.
406
+ #
407
+ # Also creates a skip_<name>_callback method that you can use to skip
408
+ # callbacks.
409
+ #
410
+ # When creating or skipping callbacks, you can specify conditions that
411
+ # are always the same for a given key. For instance, in ActionPack,
412
+ # we convert :only and :except conditions into per-key conditions.
413
+ #
414
+ # before_filter :authenticate, :except => "index"
415
+ # becomes
416
+ # dispatch_callback :before, :authenticate, :per_key => {:unless => proc {|c| c.action_name == "index"}}
417
+ #
418
+ # Per-Key conditions are evaluated only once per use of a given key.
419
+ # In the case of the above example, you would do:
420
+ #
421
+ # run_dispatch_callbacks(action_name) { ... dispatch stuff ... }
422
+ #
423
+ # In that case, each action_name would get its own compiled callback
424
+ # method that took into consideration the per_key conditions. This
425
+ # is a speed improvement for ActionPack.
426
+ def define_callbacks(*symbols)
427
+ terminator = symbols.pop if symbols.last.is_a?(String)
428
+ symbols.each do |symbol|
429
+ self.extlib_inheritable_accessor("_#{symbol}_terminator")
430
+ self.send("_#{symbol}_terminator=", terminator)
431
+ self.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
432
+ extlib_inheritable_accessor :_#{symbol}_callbacks
433
+ self._#{symbol}_callbacks = CallbackChain.new(:#{symbol})
434
+
435
+ def self.#{symbol}_callback(*filters, &blk)
436
+ type = [:before, :after, :around].include?(filters.first) ? filters.shift : :before
437
+ options = filters.last.is_a?(Hash) ? filters.pop : {}
438
+ filters.unshift(blk) if block_given?
439
+
440
+ filters.map! do |filter|
441
+ # overrides parent class
442
+ self._#{symbol}_callbacks.delete_if {|c| c.matches?(type, :#{symbol}, filter)}
443
+ Callback.new(filter, type, options.dup, self, :#{symbol})
444
+ end
445
+ self._#{symbol}_callbacks.push(*filters)
446
+ _define_runner(:#{symbol},
447
+ self._#{symbol}_callbacks.compile(nil, :terminator => _#{symbol}_terminator),
448
+ options)
449
+ end
450
+
451
+ def self.skip_#{symbol}_callback(*filters, &blk)
452
+ type = [:before, :after, :around].include?(filters.first) ? filters.shift : :before
453
+ options = filters.last.is_a?(Hash) ? filters.pop : {}
454
+ filters.unshift(blk) if block_given?
455
+ filters.each do |filter|
456
+ self._#{symbol}_callbacks = self._#{symbol}_callbacks.clone(self)
457
+
458
+ filter = self._#{symbol}_callbacks.find {|c| c.matches?(type, :#{symbol}, filter) }
459
+ per_key = options[:per_key] || {}
460
+ if filter
461
+ filter.recompile!(options, per_key)
462
+ else
463
+ self._#{symbol}_callbacks.delete(filter)
464
+ end
465
+ _define_runner(:#{symbol},
466
+ self._#{symbol}_callbacks.compile(nil, :terminator => _#{symbol}_terminator),
467
+ options)
468
+ end
469
+
470
+ end
471
+
472
+ def self.reset_#{symbol}_callbacks
473
+ self._#{symbol}_callbacks = CallbackChain.new(:#{symbol})
474
+ _define_runner(:#{symbol}, self._#{symbol}_callbacks.compile, {})
475
+ end
476
+
477
+ self.#{symbol}_callback(:before)
478
+ RUBY_EVAL
479
+ end
480
+ end
481
+ end
482
+ end
483
+ end