activerabbit 0.0.1.beta1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9312851949bab1748e88bc939dead804a6a7fbf6
4
+ data.tar.gz: a2fd8ec02623cc4df00597a414af1cf38b2986f6
5
+ SHA512:
6
+ metadata.gz: 01562dbb951775ffe7d124e322aca6e109a85b4a88240051985ad8a4ac3219a4dce42c2f52dc7399b8c0f4fca6f3f45d965949c76c412bc39280d4b00108446f
7
+ data.tar.gz: f23d84c3768e817bd84a3c4a6c7195ca2726b5cd5cd06943c883d95c71f5b9189df622411b917f084abde288d027dddbdadb839d9272484a402b957628e1d31f
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .DS_Store
2
+ .idea
3
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=documentation
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.4
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ ActiveRabbit
2
+ ============
3
+
4
+ Easy to use workers for RabbitMQ + Ruby
5
+
6
+ **Work in progress**
7
+
8
+ ## Getting Started
9
+ Define your exchanges:
10
+
11
+ ```ruby
12
+ # config/rabbit/exchanges.rb
13
+ ActiveRabbit.configuration.exchanges.draw do
14
+ topic :logs
15
+ namespace :actions do
16
+ direct :login
17
+ end
18
+ end
19
+ ```
20
+
21
+ Define your queues:
22
+
23
+ ```ruby
24
+ # config/rabbit/queues.rb
25
+ ActiveRabbit.configuration.queues.draw do
26
+ queue :log_queue, bind: :logs, routing_key: '*.critical', exclusive: true
27
+ end
28
+ ```
29
+
30
+
31
+ Define your worker:
32
+
33
+ ```ruby
34
+ # app/rabbit_consumers/log_queue_consumer.rb
35
+ class LogQueueConsumer < ActiveRabbit::Consumer
36
+
37
+ def consume
38
+ puts message
39
+ puts message.body
40
+ end
41
+ end
42
+ ```
43
+
44
+ Publish to exchanges:
45
+
46
+ ```ruby
47
+ message = 'Hello World!'
48
+ ActiveRabbit.publish('actions.login', message)
49
+ ```
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new
6
+
7
+ task :default => :spec
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'active_rabbit/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "activerabbit"
8
+ spec.version = ActiveRabbit::VERSION
9
+ spec.authors = ['Christopher Thornton']
10
+ spec.email = ['rmdirbin@gmail.com']
11
+ spec.summary = %q{RabbitMQ publishers & consumers in a rails-inspired syntax}
12
+ # spec.description = %q{TODO: Write a longer description. Optional.}
13
+ spec.homepage = 'https://github.com/cgthornt/activerabbit'
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+ spec.required_ruby_version = '>= 2.0'
21
+
22
+ spec.add_dependency 'bunny', '~> 2.0'
23
+ spec.add_dependency 'json'
24
+
25
+ spec.add_development_dependency 'rake', '~> 10.3.2'
26
+ spec.add_development_dependency 'rspec', '~> 3.1'
27
+ spec.add_development_dependency 'pry', '~> 0.9'
28
+ spec.add_development_dependency 'awesome_print'
29
+ end
@@ -0,0 +1,3 @@
1
+ ActiveRabbit.configuration.exchanges.draw do
2
+ direct :direct
3
+ end
@@ -0,0 +1,4 @@
1
+ ActiveRabbit.configuration.queues.draw do
2
+ queue :notifications, bind: :direct
3
+ queue :logs, bind: :direct
4
+ end
@@ -0,0 +1,3 @@
1
+ development:
2
+ default:
3
+ host: localhost
data/example/run.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'bundler/setup'
2
+ require 'pry'
3
+ require 'awesome_print'
4
+ require 'activerabbit'
5
+
6
+ ActiveRabbit.load_config_directory('example/rabbit')
7
+ config = ActiveRabbit.configuration
8
+ x = config.get_exchange(:direct)
9
+ x.publish("I am a notification", routing_key: 'notifications')
10
+ x.publish('I am a log', routing_key: 'logs')
11
+
12
+ class FakeConsumer < ActiveRabbit::Consumer
13
+ bind :notifications, to: :notification_action
14
+ bind :logs, to: :log_action
15
+
16
+ def notification_action
17
+ binding.pry
18
+ end
19
+
20
+ def log_action
21
+ binding.pry
22
+ end
23
+ end
24
+
25
+ runner = ActiveRabbit::Runner.new(ActiveRabbit.configuration, FakeConsumer)
26
+
27
+ runner.run!.wait!
@@ -0,0 +1,42 @@
1
+ require 'bunny'
2
+ require 'active_rabbit/version'
3
+ require 'logger'
4
+
5
+ module ActiveRabbit
6
+ autoload :Bundle, 'active_rabbit/bundle'
7
+ autoload :Configuration, 'active_rabbit/configuration'
8
+ autoload :Consumer, 'active_rabbit/consumer'
9
+ autoload :Loggable, 'active_rabbit/loggable'
10
+ autoload :Message, 'active_rabbit/message'
11
+ autoload :Runner, 'active_rabbit/runner'
12
+ autoload :Util, 'active_rabbit/util'
13
+
14
+ class << self
15
+ attr_writer :logger
16
+
17
+ def version
18
+ VERSION
19
+ end
20
+
21
+ def logger
22
+ @logger = Logger.new(STDOUT)
23
+ end
24
+
25
+ def configuration
26
+ @default_bundle ||= Bundle.new
27
+ end
28
+
29
+ def load_config_directory(directory_path)
30
+ configuration.load_directory(directory_path)
31
+ end
32
+
33
+ def temporarily_taint_configuration(bundle)
34
+ raise ArgumentError, 'No block given' unless block_given?
35
+ original_bundle = configuration
36
+ @default_bundle = bundle
37
+ yield
38
+ ensure
39
+ @default_bundle = original_bundle
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,73 @@
1
+ require 'thread'
2
+
3
+ module ActiveRabbit
4
+
5
+ # A giant blob of configuration objects into a single package
6
+ class Bundle
7
+ LOAD_DIRECTORY_MUTEX = Mutex.new
8
+
9
+ # @return [SessionLoader]
10
+ attr_accessor :session_loader
11
+
12
+ # @return [Exchange::ExchangeContext]
13
+ attr_accessor :exchange_context
14
+
15
+ # @return [Queue::QueueContext]
16
+ attr_accessor :queue_context
17
+
18
+ attr_reader :loaded_sessions
19
+
20
+ attr_accessor :environment
21
+
22
+ alias_method :exchanges, :exchange_context
23
+ alias_method :queues, :queue_context
24
+
25
+ def initialize(environment: nil)
26
+ @exchange_context = Configuration::Exchange::ExchangeContext.new
27
+ @queue_context = Configuration::Queue::QueueContext.new
28
+ @session_loader = Configuration::SessionLoader.new
29
+ @loaded_sessions = {}
30
+ @environment = environment || ENV['ACTIVERABBIT_ENV'] || 'development'
31
+ end
32
+
33
+ def load_directory(directory_path)
34
+ LOAD_DIRECTORY_MUTEX.synchronize do
35
+ ActiveRabbit.temporarily_taint_configuration(self) do
36
+ glob = File.join(directory_path, '**', '*.rb')
37
+ Dir[glob].each do |file|
38
+ require File.expand_path(file)
39
+ end
40
+
41
+ config_file = File.join(directory_path, 'sessions.yml')
42
+ if File.exist?(config_file)
43
+ session_loader.load_yaml_file!(config_file, environment)
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ def get_session(name)
50
+ loaded_sessions[name] ||= session_loader.to_session(name).tap do |session|
51
+ session.start
52
+ end
53
+ end
54
+
55
+ def get_channel(name, thread = Thread.current)
56
+ thread["activerabbit_bundle_#{name}"] ||= get_session(name).create_channel
57
+ end
58
+
59
+ def get_exchange(qualified_name)
60
+ exchange_value = exchange_context.search_values!(qualified_name)
61
+ exchange_value.to_exchange(self)
62
+ end
63
+
64
+ def get_and_bind_queue(qualified_name)
65
+ queue_value = queue_context.search_values!(qualified_name)
66
+ queue_value.get_and_bind_queue(self)
67
+ end
68
+
69
+ def publish(qualified_name, message, publish_options = {})
70
+ get_exchange(qualified_name).publish(message, publish_options)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,8 @@
1
+ module ActiveRabbit
2
+ module Configuration
3
+ autoload :Context, 'active_rabbit/configuration/context'
4
+ autoload :Exchange, 'active_rabbit/configuration/exchange'
5
+ autoload :SessionLoader, 'active_rabbit/configuration/session_loader'
6
+ autoload :Queue, 'active_rabbit/configuration/Queue'
7
+ end
8
+ end
@@ -0,0 +1,123 @@
1
+ module ActiveRabbit::Configuration
2
+ class Context
3
+ attr_reader :parent_context
4
+
5
+ attr_reader :default_options
6
+
7
+ attr_reader :child_contexes
8
+
9
+ attr_reader :namespace_name
10
+
11
+ attr_reader :config_values
12
+
13
+ def initialize(namespace_name = nil, parent_context = nil, default_options = {})
14
+ @parent_context = parent_context
15
+ @default_options = default_options
16
+ @child_contexes = {}
17
+ @config_values = {}
18
+ @namespace_name = normalize_name(namespace_name) if namespace_name
19
+ if parent_context && parent_context.namespace_name && !parent_context.namespace_name.empty?
20
+ @namespace_name = "#{parent_context.namespace_name}.#{@namespace_name}"
21
+ @default_options = parent_context.default_options.merge!(default_options)
22
+ end
23
+ @default_options = default_default_options.merge(@default_options)
24
+ end
25
+
26
+ def default_default_options
27
+ {
28
+ session: :default
29
+ }
30
+ end
31
+
32
+ def qualify_name(name)
33
+ name = normalize_name(name)
34
+ if namespace_name && !namespace_name.empty?
35
+ "#{namespace_name}.#{name}"
36
+ else
37
+ name
38
+ end
39
+ end
40
+
41
+ def normalize_name(name)
42
+ if name.is_a?(Symbol)
43
+ name.to_s.gsub('_', '-')
44
+ elsif name.is_a?(String)
45
+ name
46
+ else
47
+ raise ArgumentError, "Expected String or Symbol, got #{name.class.name}"
48
+ end
49
+ end
50
+
51
+ def add_config_value(unqualified_name, value)
52
+ config_values[qualify_name(unqualified_name)] = value
53
+ end
54
+
55
+ def effective_options(options = {})
56
+ default_options.merge(options)
57
+ end
58
+
59
+ def parent_context?
60
+ !parent_context.nil?
61
+ end
62
+
63
+ def defaults(options = {})
64
+ default_options.merge!(options)
65
+ end
66
+
67
+ def namespace(name, default_options = {}, &block)
68
+ raise ArgumentError, 'block not given' unless block_given?
69
+ name = normalize_name(name)
70
+ context = self.class.new(name, self, default_options)
71
+ context.configure(&block)
72
+ child_contexes[name] = context
73
+ end
74
+
75
+ # Given a fully qualified value, i.e. "some.namespace.some-value",
76
+ # returns that value, or nil
77
+ def search_values(fully_qualified_name)
78
+ search_pieces(normalize_name(fully_qualified_name).split('.'))
79
+ end
80
+
81
+ def search_values!(fully_qualified_name)
82
+ search_values(fully_qualified_name) || raise(ArgumentError, "Unknown value '#{fully_qualified_name}'")
83
+ end
84
+
85
+ def search_pieces(fully_qualified_name_array)
86
+ # Last item
87
+ if !fully_qualified_name_array.any?
88
+ return nil
89
+ elsif fully_qualified_name_array.size == 1
90
+ item = fully_qualified_name_array[0]
91
+ return config_values[item]
92
+ else
93
+ search = fully_qualified_name_array.shift
94
+ if(context = child_contexes[search])
95
+ return context.search_pieces(fully_qualified_name_array)
96
+ else
97
+ return null
98
+ end
99
+ end
100
+ end
101
+
102
+ def configure(&block)
103
+ instance_eval(&block)
104
+ end
105
+ alias_method :draw, :configure
106
+
107
+ def flatten_contexes
108
+ all_contexes = [this]
109
+ child_contexes.values.each do |child|
110
+ all_contexes.concat(child.flatten_contexes)
111
+ end
112
+ all_contexes
113
+ end
114
+
115
+ def all_values
116
+ values = config_values.dup
117
+ child_contexes.values.each do |child|
118
+ values.merge!(child.all_values)
119
+ end
120
+ values
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,27 @@
1
+ module ActiveRabbit::Configuration
2
+ module Exchange
3
+ class ExchangeContext < Context
4
+ def exchange(name, type, options = {})
5
+ # TODO: allow overriding name outside of convention
6
+ add_config_value(name, Value.new(qualify_name(name), type.to_sym, effective_options(options)))
7
+ end
8
+
9
+ def direct(name, options = {})
10
+ exchange(name, :direct, options)
11
+ end
12
+
13
+ def topic(name, options = {})
14
+ exchange(name, :topic, options)
15
+ end
16
+ end
17
+
18
+ # Maps to a Bunny::Exchange
19
+ class Value < Struct.new(:name, :type, :options)
20
+ def to_exchange(bundle)
21
+ Bunny::Exchange.new(
22
+ bundle.get_channel(options.fetch(:session)),
23
+ type, name, options)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,77 @@
1
+ module ActiveRabbit::Configuration
2
+ module Queue
3
+ class QueueContext < Context
4
+ def queue(name, options = {})
5
+ options = {routing_key: name.to_s}.merge(options.dup)
6
+ queue_name = options.delete(:name) || qualify_name(name)
7
+ value = Value.new(queue_name, effective_options(options))
8
+ add_config_value(name, value)
9
+ end
10
+
11
+ def durable(name, options = {})
12
+ queue(name, options.merge(durable: true))
13
+ end
14
+
15
+ def temporary(name, options = {})
16
+ queue(name, options.merge(exclusive: true, name: ''))
17
+ end
18
+ end
19
+
20
+ class Value < Struct.new(:queue_name, :options)
21
+ QUEUE_ONLY_KEYS = [:durable, :auto_delete, :exclusive, :arguments]
22
+
23
+ def qualified_exchange_name
24
+ @qualified_exchange_name ||= (options[:bind] || options[:exchange] || options[:x]).to_s
25
+ end
26
+
27
+ def routing_key
28
+ options[:routing_key]
29
+ end
30
+
31
+ def queue_only_options
32
+ ActiveRabbit::Util.hash_only_keys(options, *QUEUE_ONLY_KEYS)
33
+ end
34
+
35
+ def bind_only_options
36
+ ActiveRabbit::Util.hash_except_keys(options, *QUEUE_ONLY_KEYS)
37
+ end
38
+
39
+ def to_queue(bundle)
40
+ get_channel(bundle).queue(queue_name, queue_only_options)
41
+ end
42
+
43
+ def get_channel(bundle)
44
+ bundle.get_channel(options.fetch(:session))
45
+ end
46
+
47
+ def bind(queue, exchange)
48
+ queue.bind(exchange, bind_only_options)
49
+ end
50
+
51
+ def get_exchange(bundle)
52
+ if qualified_exchange_name.nil?
53
+ raise ArgumentError, 'No exchange name set; ensure in your exchange definition your queue is bound to an exchange'
54
+ end
55
+
56
+ exchange_value = bundle.exchange_context.search_values(qualified_exchange_name)
57
+
58
+ if exchange_value.nil?
59
+ raise ArgumentError, "Unknown exchange name '#{qualified_exchange_name}'; perhaps it is not defined?"
60
+ end
61
+
62
+ if exchange_value.options[:session] != options[:session]
63
+ raise ArgumentError, "Queue session does not match binded queue's session"
64
+ end
65
+
66
+ exchange_value.to_exchange(bundle)
67
+ end
68
+
69
+ def get_and_bind_queue(bundle)
70
+ queue = to_queue(bundle)
71
+ exchange = get_exchange(bundle)
72
+ bind(queue, exchange)
73
+ queue
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,24 @@
1
+ require 'yaml'
2
+
3
+ module ActiveRabbit::Configuration
4
+
5
+ # Specifies a bunch of Bunny configurations
6
+ class SessionLoader < Hash
7
+ alias_method :define, :[]=
8
+
9
+ def load_yaml_file!(path_to_yaml, env)
10
+ results = YAML.load_file(path_to_yaml).fetch(env.to_s)
11
+ merge!(results)
12
+ end
13
+
14
+ def default
15
+ self['default']
16
+ end
17
+
18
+ def to_session(name)
19
+ value = fetch(name.to_s)
20
+ return value if value.is_a?(Bunny::Session)
21
+ Bunny::Session.new(value)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,39 @@
1
+ module ActiveRabbit
2
+ class Consumer
3
+ class Binding < Struct.new(:queue_name, :method_name)
4
+ end
5
+
6
+ class << self
7
+ def bind(*queue_names, to:)
8
+ bindings.concat(queue_names.map do |queue_name|
9
+ Binding.new(queue_name, to)
10
+ end.to_a)
11
+ end
12
+
13
+ def bindings
14
+ @bindings ||= []
15
+ end
16
+
17
+ def process_message!(channel, method, message)
18
+ self.new(channel, message).send(method)
19
+ end
20
+ end
21
+
22
+ attr_reader :message, :_channel
23
+
24
+ def initialize(channel, message)
25
+ @message = message
26
+ @_channel = channel
27
+ end
28
+
29
+ def ack!(multiple = false)
30
+ _channel.acknowledge(message.delivery_info.delivery_tag, multiple)
31
+ end
32
+
33
+ def params
34
+ message.params
35
+ end
36
+
37
+
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ module ActiveRabbit
2
+ module Loggable
3
+ def logger
4
+ ActiveRabbit.logger
5
+ end
6
+
7
+ def self.included(base)
8
+ base.extend Loggable
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,32 @@
1
+ require 'json'
2
+
3
+ module ActiveRabbit
4
+ class Message
5
+ attr_reader :delivery_info, :properties, :body
6
+
7
+ def initialize(delivery_info, properties, body)
8
+ @delivery_info = delivery_info
9
+ @properties = properties
10
+ @body = body
11
+ end
12
+
13
+ def params
14
+ defined?(@params) ? @params : @params = calculate_params
15
+ end
16
+
17
+ def content_type
18
+ properties[:content_type].to_s.downcase
19
+ end
20
+
21
+ def routing_key
22
+ delivery_info[:routing_key]
23
+ end
24
+
25
+ protected
26
+
27
+ # TODO: allow parsing of other param types
28
+ def calculate_params
29
+ content_type == 'application/json' ? JSON.parse(body) : nil
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,68 @@
1
+ require 'set'
2
+
3
+ module ActiveRabbit
4
+ class Runner
5
+ include Loggable
6
+
7
+ attr_reader :bundle
8
+
9
+ attr_reader :consumer_klasses
10
+
11
+ attr_reader :bunny_consumers
12
+
13
+ def initialize(bundle, consumer_klasses)
14
+ @bundle = bundle
15
+ @consumer_klasses = Util.array_wrap(consumer_klasses)
16
+ @bunny_consumers = []
17
+ end
18
+
19
+ def run!
20
+ consumer_klasses.each do |klass|
21
+ run_consumer_klass(klass)
22
+ end
23
+ self
24
+ end
25
+
26
+ def wait!
27
+ logger.info 'Joining worker threads. INTERRUPT or Ctrl-C to exit'
28
+ joined = Set.new
29
+ bunny_consumers.each do |bunny_consumer|
30
+ channel = bunny_consumer.channel
31
+ next if joined.include?(channel)
32
+ joined << channel
33
+ channel.work_pool.join
34
+ end
35
+ rescue Interrupt => _
36
+ puts 'Exiting...'
37
+ end
38
+
39
+ protected
40
+
41
+ def run_consumer_klass(klass)
42
+ unless klass.bindings.any?
43
+ logger.warn "Consumer #{klass.name} does not bind to any queues; ignoring"
44
+ return
45
+ end
46
+
47
+ klass.bindings.each do |binding|
48
+ run_binding(klass, binding)
49
+ end
50
+ end
51
+
52
+ def run_binding(consumer_klass, binding)
53
+ unless consumer_klass.instance_methods(false).include?(binding.method_name)
54
+ raise "#{consumer_klass.name} does not define a method #{binding.method_name}"
55
+ end
56
+
57
+ queue_value = bundle.queue_context.search_values!(binding.queue_name)
58
+ queue = bundle.get_and_bind_queue(binding.queue_name)
59
+ bunny_consumer = queue.subscribe do |delivery_info,properties,body|
60
+ message = ActiveRabbit::Message.new(delivery_info, properties, body)
61
+ consumer_klass.process_message!(queue.channel, binding.method_name, message)
62
+ end
63
+ logger.info "Bound #{consumer_klass.name}##{binding.method_name} to queue '#{queue_value.queue_name}' (rabbitmq name: #{queue.name})"
64
+ @bunny_consumers << bunny_consumer
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,54 @@
1
+ # Because we don't want to import ActiveSupport
2
+ module ActiveRabbit::Util
3
+ def self.hash_only_keys(hash, *only_keys)
4
+ new_hash = {}
5
+ union_keys = hash.keys | only_keys
6
+ union_keys.each do |key|
7
+ new_hash[key] = hash[key]
8
+ end
9
+ return new_hash
10
+ end
11
+
12
+ def self.hash_except_keys(hash, *except_keys)
13
+ new_hash = {}
14
+ new_keys = hash.keys - except_keys
15
+ new_keys.each do |key|
16
+ new_hash[key] = hash[key]
17
+ end
18
+ return new_hash
19
+ end
20
+
21
+ def self.string_underscore(camel_cased_word)
22
+ camel_cased_word.to_s.gsub(/::/, '/').
23
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
24
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
25
+ tr("-", "_").
26
+ downcase
27
+ end
28
+
29
+ def self.string_camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
30
+ if first_letter_in_uppercase
31
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
32
+ else
33
+ lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
34
+ end
35
+ end
36
+
37
+ def self.string_constantize(camel_cased_word)
38
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
39
+ raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
40
+ end
41
+
42
+ Object.module_eval("::#{$1}", __FILE__, __LINE__)
43
+ end
44
+
45
+ def self.array_wrap(object)
46
+ if object.nil?
47
+ []
48
+ elsif object.respond_to?(:to_ary)
49
+ object.to_ary || [object]
50
+ else
51
+ [object]
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveRabbit
2
+ VERSION = '0.0.1.beta1'
3
+ end
@@ -0,0 +1 @@
1
+ require 'active_rabbit'
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRabbit::Configuration::Exchange do
4
+
5
+ it 'supports a configuration block' do
6
+ context = ActiveRabbit::Configuration::Exchange::ExchangeContext.new
7
+ context.configure do
8
+ direct 'top-level'
9
+ namespace :my_namespace do
10
+ direct 'nested'
11
+ end
12
+ end
13
+
14
+ binding.pry
15
+
16
+ end
17
+
18
+
19
+ end
@@ -0,0 +1,6 @@
1
+ # Here for the future
2
+
3
+ require 'active_rabbit'
4
+
5
+ require 'pry'
6
+ require 'awesome_print'
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerabbit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.beta1
5
+ platform: ruby
6
+ authors:
7
+ - Christopher Thornton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bunny
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 10.3.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 10.3.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.9'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.9'
83
+ - !ruby/object:Gem::Dependency
84
+ name: awesome_print
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description:
98
+ email:
99
+ - rmdirbin@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - ".ruby-version"
107
+ - Gemfile
108
+ - README.md
109
+ - Rakefile
110
+ - activerabbit.gemspec
111
+ - example/rabbit/exchanges.rb
112
+ - example/rabbit/queues.rb
113
+ - example/rabbit/sessions.yml
114
+ - example/run.rb
115
+ - lib/active_rabbit.rb
116
+ - lib/active_rabbit/bundle.rb
117
+ - lib/active_rabbit/configuration.rb
118
+ - lib/active_rabbit/configuration/context.rb
119
+ - lib/active_rabbit/configuration/exchange.rb
120
+ - lib/active_rabbit/configuration/queue.rb
121
+ - lib/active_rabbit/configuration/session_loader.rb
122
+ - lib/active_rabbit/consumer.rb
123
+ - lib/active_rabbit/loggable.rb
124
+ - lib/active_rabbit/message.rb
125
+ - lib/active_rabbit/runner.rb
126
+ - lib/active_rabbit/util.rb
127
+ - lib/active_rabbit/version.rb
128
+ - lib/activerabbit.rb
129
+ - spec/lib/active_rabbit/configuration/exchange_spec.rb
130
+ - spec/spec_helper.rb
131
+ homepage: https://github.com/cgthornt/activerabbit
132
+ licenses:
133
+ - MIT
134
+ metadata: {}
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '2.0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">"
147
+ - !ruby/object:Gem::Version
148
+ version: 1.3.1
149
+ requirements: []
150
+ rubyforge_project:
151
+ rubygems_version: 2.4.5.1
152
+ signing_key:
153
+ specification_version: 4
154
+ summary: RabbitMQ publishers & consumers in a rails-inspired syntax
155
+ test_files:
156
+ - spec/lib/active_rabbit/configuration/exchange_spec.rb
157
+ - spec/spec_helper.rb