activerabbit 0.0.1.beta1

Sign up to get free protection for your applications and to get access to all the features.
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