messed 0.0.1

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.
Files changed (102) hide show
  1. data/Gemfile +8 -0
  2. data/README.rdoc +22 -0
  3. data/Rakefile +76 -0
  4. data/VERSION +1 -0
  5. data/application_spec/Rakefile +12 -0
  6. data/application_spec/app/runner.rb +3 -0
  7. data/application_spec/bin/runner +18 -0
  8. data/application_spec/bin/status +36 -0
  9. data/application_spec/bin/web +29 -0
  10. data/application_spec/config/environment.rb +8 -0
  11. data/application_spec/config/environments/development.rb +0 -0
  12. data/application_spec/log/development.log +6 -0
  13. data/application_spec/spec/application_spec.rb +12 -0
  14. data/application_spec/spec/spec.opts +7 -0
  15. data/application_spec/spec/spec_helper.rb +42 -0
  16. data/bin/messed +9 -0
  17. data/lib/messed/booter.rb +114 -0
  18. data/lib/messed/configuration.rb +94 -0
  19. data/lib/messed/controller/helper.rb +8 -0
  20. data/lib/messed/controller/processing.rb +22 -0
  21. data/lib/messed/controller/respond.rb +48 -0
  22. data/lib/messed/controller.rb +17 -0
  23. data/lib/messed/em_runner.rb +50 -0
  24. data/lib/messed/interface/adapter/sms.rb +4 -0
  25. data/lib/messed/interface/adapter/twitter_consumer.rb +35 -0
  26. data/lib/messed/interface/adapter/twitter_search.rb +111 -0
  27. data/lib/messed/interface/adapter/twitter_sender.rb +44 -0
  28. data/lib/messed/interface/adapter/twitter_streaming.rb +50 -0
  29. data/lib/messed/interface/adapter.rb +68 -0
  30. data/lib/messed/interface/runner.rb +20 -0
  31. data/lib/messed/interface.rb +74 -0
  32. data/lib/messed/logger.rb +50 -0
  33. data/lib/messed/matcher.rb +50 -0
  34. data/lib/messed/message/twitter.rb +23 -0
  35. data/lib/messed/message.rb +35 -0
  36. data/lib/messed/queue/beanstalk.rb +56 -0
  37. data/lib/messed/queue.rb +17 -0
  38. data/lib/messed/session/memcache.rb +40 -0
  39. data/lib/messed/session.rb +7 -0
  40. data/lib/messed/tasks/console.rb +70 -0
  41. data/lib/messed/tasks/generation.rb +12 -0
  42. data/lib/messed/tasks/runner.rb +50 -0
  43. data/lib/messed/tasks/status.rb +37 -0
  44. data/lib/messed/tasks.rb +9 -0
  45. data/lib/messed/util/remote_status.rb +45 -0
  46. data/lib/messed.rb +235 -0
  47. data/patterns/messed/Pattern +24 -0
  48. data/patterns/messed/Rakefile +12 -0
  49. data/patterns/messed/app/runner.rb +5 -0
  50. data/patterns/messed/bin/console +3 -0
  51. data/patterns/messed/bin/runner +3 -0
  52. data/patterns/messed/bin/status +3 -0
  53. data/patterns/messed/bin/web +13 -0
  54. data/patterns/messed/config/environment.rb +15 -0
  55. data/patterns/messed/config/environments/development.rb +2 -0
  56. data/patterns/messed/config/environments/production.rb +0 -0
  57. data/patterns/messed/config/environments/test.rb +0 -0
  58. data/patterns/messed/spec/application_spec.rb +12 -0
  59. data/patterns/messed/spec/spec.opts +7 -0
  60. data/patterns/messed/spec/spec_helper.rb +44 -0
  61. data/spec/adapter/applications/twitter_search/app/application.rb +3 -0
  62. data/spec/adapter/applications/twitter_search/app/runner.rb +7 -0
  63. data/spec/adapter/applications/twitter_search/bin/incoming +89 -0
  64. data/spec/adapter/applications/twitter_search/bin/runner +21 -0
  65. data/spec/adapter/applications/twitter_search/bin/status +36 -0
  66. data/spec/adapter/applications/twitter_search/config/environment.rb +11 -0
  67. data/spec/adapter/applications/twitter_search/config/environments/development.rb +0 -0
  68. data/spec/adapter/applications/twitter_search/log/development.log +1006 -0
  69. data/spec/adapter/applications/twitter_sender/app/application.rb +0 -0
  70. data/spec/adapter/applications/twitter_sender/app/runner.rb +0 -0
  71. data/spec/adapter/applications/twitter_sender/bin/incoming +89 -0
  72. data/spec/adapter/applications/twitter_sender/bin/runner +21 -0
  73. data/spec/adapter/applications/twitter_sender/bin/status +36 -0
  74. data/spec/adapter/applications/twitter_sender/config/environment.rb +11 -0
  75. data/spec/adapter/applications/twitter_sender/config/environments/development.rb +0 -0
  76. data/spec/adapter/applications/twitter_sender/log/development.log +146 -0
  77. data/spec/adapter/http/direct_message +0 -0
  78. data/spec/adapter/http/twitter_search +20 -0
  79. data/spec/adapter/http/update +0 -0
  80. data/spec/adapter/twitter_search_spec.rb +36 -0
  81. data/spec/adapter/twitter_sender_spec.rb +64 -0
  82. data/spec/booter_spec.rb +7 -0
  83. data/spec/fixtures/booter/app/application.rb +3 -0
  84. data/spec/fixtures/booter/app/runner.rb +7 -0
  85. data/spec/fixtures/booter/bin/incoming +89 -0
  86. data/spec/fixtures/booter/bin/runner +21 -0
  87. data/spec/fixtures/booter/bin/status +36 -0
  88. data/spec/fixtures/booter/config/environment.rb +15 -0
  89. data/spec/fixtures/booter/config/environments/development.rb +0 -0
  90. data/spec/fixtures/booter/log/development.log +11 -0
  91. data/spec/message_spec.rb +52 -0
  92. data/spec/session_spec.rb +34 -0
  93. data/spec/spec.opts +7 -0
  94. data/spec/spec_helper.rb +8 -0
  95. data/test/app/runner.rb +5 -0
  96. data/test/config/environment.rb +15 -0
  97. data/test/config/environments/development.rb +2 -0
  98. data/test/config/environments/production.rb +0 -0
  99. data/test/config/environments/test.rb +0 -0
  100. data/test/spec/application_spec.rb +12 -0
  101. data/test/spec/spec_helper.rb +44 -0
  102. metadata +291 -0
@@ -0,0 +1,70 @@
1
+ class Messed
2
+ module Tasks
3
+ class Console
4
+
5
+ module KeyboardHandler
6
+ include EM::Protocols::LineText2
7
+
8
+ attr_accessor :root, :environment
9
+
10
+ def log_outgoing(responses)
11
+ if responses.empty?
12
+ puts "No responses"
13
+ else
14
+ puts "Responding ... #{responses.map{|r| "`#{r.body}'"}.join(', ')}"
15
+ end
16
+ end
17
+
18
+ def prompt
19
+ $stdout << ">> "
20
+ $stdout.flush
21
+ end
22
+
23
+ def post_init
24
+ print_banner
25
+ prompt
26
+ end
27
+
28
+ def print_banner
29
+ puts "? help"
30
+ puts "!q quit"
31
+ puts "Eventhing else is a message"
32
+ end
33
+
34
+ def receive_line(data)
35
+ case data.strip
36
+ when '!q'
37
+ EM.stop_event_loop
38
+ exit
39
+ when '?'
40
+ print_banner
41
+ else
42
+ pid = EM.fork_reactor do
43
+ Booter.new(root, :environment => environment, :supress_banner => true) do |booter|
44
+ Messed::Logger.instance.setup_logger(::Logger.new(STDOUT), :debug)
45
+ log_outgoing(booter.application.process(booter.application.message_class.new(data.strip)))
46
+ EM.stop_event_loop
47
+ end
48
+ end
49
+ Process.wait(pid)
50
+ end
51
+ prompt
52
+ end
53
+ end
54
+
55
+ def self.start
56
+ new.start
57
+ end
58
+
59
+ def start
60
+ EM.run do
61
+ EM.open_keyboard(KeyboardHandler) do |handler|
62
+ handler.root = $root
63
+ handler.environment = ARGV[0]
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,12 @@
1
+ class Messed
2
+ module Tasks
3
+ class Generation
4
+
5
+ def initialize(name)
6
+ Dressmaker.new(File.join(File.dirname(__FILE__), '..', '..', '..', 'patterns', 'messed'), File.join(Dir.pwd, name)).generate(:app_name => name)
7
+ end
8
+
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,50 @@
1
+ class Messed
2
+ module Tasks
3
+ class Runner < Thor
4
+
5
+ method_options %w( environment -e ) => "development"
6
+ method_options %w( detach -d ) => false
7
+ desc "interface [NAME] [CMD]", "starts an interface (start|stop)"
8
+ def interface(name, cmd)
9
+ case cmd
10
+ when 'start'
11
+ Messed::Booter.new($root, :detach => options.detach?, :environment => options.environment) do |booter|
12
+ interface = booter.interface_for(name.to_sym)
13
+ raise("unable to find an interface with name the `#{name}'") unless interface
14
+ interface.start
15
+ end
16
+ when 'stop'
17
+ Messed::Booter.new($root, :environment => options.environment).interface_for(name.to_sym).stop
18
+ end
19
+ end
20
+
21
+ method_options %w( environment -e ) => "development"
22
+ method_options %w( detach -d ) => false
23
+ desc "application [CMD]", "start the application (start|stop)"
24
+ def application(cmd)
25
+ case cmd
26
+ when 'start'
27
+ Messed::Booter.new($root, :detach => options.detach?, :environment => options.environment) do |booter|
28
+ application = booter.application
29
+ application.start
30
+ end
31
+ when 'stop'
32
+ Messed::Booter.new($root, :environment => options.environment).application.stop
33
+ end
34
+ end
35
+
36
+ method_options %w( environment -e ) => "development"
37
+ method_options %w( detach -d ) => false
38
+ desc "start all interfaces and application [NAME]", "starts all"
39
+ def all
40
+ Messed::Booter.new($root, :detach => options.detach?, :environment => options.environment) do |booter|
41
+ booter.configuration.interfaces.names.each do |name|
42
+ booter.interface_for(name.to_sym).start
43
+ end
44
+ booter.application.start
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,37 @@
1
+ class Messed
2
+ module Tasks
3
+ class Status < Thor
4
+
5
+ desc "Status", "status"
6
+ method_options :environment => "development"
7
+ def status
8
+ booter = Messed::Booter.new($root, options.environment)
9
+
10
+ puts "=Queues"
11
+ puts "==Incoming"
12
+ booter.application.incoming.status.each {|k,v|
13
+ puts " %40s - %s" % [k, v]
14
+ }
15
+
16
+ puts "==Outgoing"
17
+ booter.application.outgoing.status.each {|k,v|
18
+ puts " %40s - %s" % [k, v]
19
+ }
20
+
21
+ puts "=Interfaces"
22
+ booter.interface_map.each {|name, interface|
23
+ puts "==#{interface.name}"
24
+ Messed::Util::RemoteStatus.new(interface.configuration.options['host'], interface.configuration.options['port']).status.each {|k,v|
25
+ puts " %40s - %s" % [k, v]
26
+ }
27
+ }
28
+
29
+ puts "=Application"
30
+ Messed::Util::RemoteStatus.new(booter.application.configuration['host'], booter.application.configuration['port']).status.each {|k,v|
31
+ puts " %40s - %s" % [k, v]
32
+ }
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ class Messed
2
+ module Tasks
3
+ autoload :Generation, File.join('messed', 'tasks', 'generation')
4
+ autoload :Runner, File.join('messed', 'tasks', 'runner')
5
+ autoload :Status, File.join('messed', 'tasks', 'status')
6
+ autoload :Web, File.join('messed', 'tasks', 'web')
7
+ autoload :Console, File.join('messed', 'tasks', 'console')
8
+ end
9
+ end
@@ -0,0 +1,45 @@
1
+ class Messed
2
+ module Util
3
+ class RemoteStatus
4
+
5
+ attr_reader :status
6
+
7
+ class StatusHandler < EM::Connection
8
+
9
+ attr_accessor :status
10
+
11
+ def post_init
12
+ puts "post..."
13
+ send_data "status\r\n"
14
+ end
15
+
16
+ def receive_data(data)
17
+ JSON.parse(data).each do |key, value|
18
+ self.status[key] = status
19
+ end
20
+ EM.stop_event_loop
21
+ end
22
+ end
23
+
24
+ def initialize(host, port)
25
+ host ||= '127.0.0.1'
26
+ @status = {}
27
+ EM.run do
28
+ EM.add_timer(5) {
29
+ @status['error'] = "timeout on connect"
30
+ EM.stop_event_loop
31
+ }
32
+ begin
33
+ EM.connect(host, port, StatusHandler) do |handler|
34
+ handler.status = @status
35
+ end
36
+ rescue
37
+ @status['error'] = "can't connect"
38
+ EM.stop_event_loop
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
data/lib/messed.rb ADDED
@@ -0,0 +1,235 @@
1
+ require 'hashify'
2
+ require 'logger'
3
+ require 'time'
4
+ require 'eventmachine'
5
+ require 'em-http'
6
+ require 'em-beanstalk'
7
+ require 'hwia'
8
+ require 'active_support'
9
+ require 'dressmaker'
10
+
11
+ $LOAD_PATH << File.dirname(__FILE__)
12
+
13
+ class Messed
14
+
15
+ autoload :Booter, File.join('messed', 'booter')
16
+ autoload :Configuration, File.join('messed', 'configuration')
17
+ autoload :Controller, File.join('messed', 'controller')
18
+ autoload :EMRunner, File.join('messed', 'em_runner')
19
+ autoload :Interface, File.join('messed', 'interface')
20
+ autoload :Logger, File.join('messed', 'logger')
21
+ autoload :Matcher, File.join('messed', 'matcher')
22
+ autoload :Message, File.join('messed', 'message')
23
+ autoload :Queue, File.join('messed', 'queue')
24
+ autoload :Session, File.join('messed', 'session')
25
+ autoload :Tasks, File.join('messed', 'tasks')
26
+ autoload :Utils, File.join('messed', 'utils')
27
+
28
+ module Util
29
+ autoload :RemoteStatus, File.join('messed', 'util', 'remote_status')
30
+ end
31
+
32
+ include Logger::LoggingModule
33
+ include Controller::Helper
34
+ include Controller::Processing
35
+ include Controller::Respond
36
+
37
+ after_processing :reset!
38
+
39
+ attr_accessor :controller, :booter, :current_matcher
40
+ attr_reader :outgoing, :incoming, :matchers, :session_store, :type, :interface, :name,
41
+ :messages_received_count, :messages_sent_count, :last_message_received, :last_message_sent
42
+
43
+ def initialize(type = :twitter, &block)
44
+ @type = type
45
+ @matchers = []
46
+ @session_store = Session::Memcache.new
47
+ @messages_sent_count = 0
48
+ @messages_received_count = 0
49
+
50
+ @interface = self
51
+ @name = 'Application'
52
+ match(&block) if block
53
+ end
54
+
55
+ def match(&block)
56
+ instance_eval(&block)
57
+ end
58
+
59
+ def reset!
60
+ matchers.clear
61
+ end
62
+
63
+ def message_class
64
+ Message.class_for_type(type)
65
+ end
66
+
67
+ def incoming=(incoming)
68
+ @incoming = incoming
69
+ incoming.application = self
70
+ end
71
+
72
+ def outgoing=(outgoing)
73
+ @outgoing = outgoing
74
+ outgoing.application = self
75
+ end
76
+
77
+ def with(*args, &block)
78
+ matchers << if args.first.is_a?(Hash)
79
+ Matcher::Conditional.new(nil, args.first)
80
+ else
81
+ Matcher::Conditional.new(*args, &block)
82
+ end
83
+ matchers.last.destination = block
84
+ end
85
+
86
+ def otherwise(options = nil, &block)
87
+ matchers << Matcher::Always.new(&block)
88
+ matchers.last.destination = block
89
+ end
90
+ alias_method :always, :otherwise
91
+
92
+ def status_port
93
+ booter.configuration.application.status_port || 19191
94
+ end
95
+
96
+ def status_host
97
+ booter.configuration.application.status_address || '0.0.0.0'
98
+ end
99
+
100
+ def start(continue_forever = true)
101
+ if EM.reactor_running?
102
+ if booter
103
+ EM.start_server(status_host, status_port, EMRunner::StatusHandler) do |c|
104
+ c.interface = self
105
+ end
106
+ logger.info "Status handler for #{self.class} started on #{status_host}:#{status_port}"
107
+ booter.write_pid_file(booter.configuration.application.pid_file)
108
+ end
109
+
110
+ @connection = EM::Beanstalk.new
111
+ @connection.watch(incoming.tube) do
112
+ @connection.use(outgoing.tube) do
113
+ process_incoming(continue_forever)
114
+ end
115
+ end
116
+ else
117
+ EM.run {
118
+ start(continue_forever)
119
+ }
120
+ end
121
+ end
122
+
123
+ def stop
124
+ Process.kill("INT", booter.read_pid_file(booter.configuration.application.pid_file))
125
+ end
126
+
127
+ def process_incoming(continue_forever)
128
+ @connection.reserve(continue_forever ? nil : 0.5) { |job|
129
+ begin
130
+ message = message_class.from_json(job.body)
131
+ process_responses process(message)
132
+ job.delete do
133
+ process_incoming(continue_forever)
134
+ end
135
+ rescue JSON::ParserError
136
+ # unrecoverable
137
+ logger.error "message #{job.body.inspect} not in JSON format"
138
+ job.delete do
139
+ process_incoming(continue_forever)
140
+ end
141
+ end
142
+ }.on_error { |message|
143
+ EM.stop_event_loop
144
+ }
145
+ end
146
+
147
+ def process(message)
148
+ logger.debug("Processing `#{message.body}'")
149
+ increment_messages_received!
150
+ responses = []
151
+
152
+ self.message = message
153
+
154
+ session_store.with(message.unique_id) do |session|
155
+ self.session = session
156
+
157
+ matchers.find do |matcher|
158
+ if matcher.match?(message)
159
+ self.current_matcher = matcher
160
+ controller = process_destination(matcher.destination)
161
+ responses.concat(controller.responses)
162
+ matcher.stop_processing?
163
+ else
164
+ false
165
+ end
166
+ end
167
+
168
+ controller.reset_processing! if controller.respond_to?(:reset_processing!)
169
+ reset_processing!
170
+ end
171
+ responses
172
+ end
173
+
174
+ def extract_destination(options, block)
175
+ block ||
176
+ {:controller => options.delete(:controller) || raise("you must supply a controller"), :action => options.delete(:action) || raise("you must supply an action")} ||
177
+ raise("you need to either supply options or a block")
178
+ end
179
+ protected :extract_destination
180
+
181
+ def reset!
182
+ self.controller = nil
183
+ self.message = nil
184
+ self.params = nil
185
+ self.session = nil
186
+ end
187
+ protected :reset!
188
+
189
+ def process_destination(destination)
190
+ if destination.respond_to?(:call)
191
+ instance_eval(&destination)
192
+ self
193
+ else
194
+ class_name = destination[:controller].to_s.split('_').map{|w| w.capitalize}.join
195
+ self.controller = Kernel.const_get(class_name.to_sym).new
196
+ self.controller.params = params if controller.respond_to?(:params=)
197
+ self.controller.message = message if controller.respond_to?(:message=)
198
+ self.controller.method(destination[:action].to_sym).call
199
+ self.controller
200
+ end
201
+ end
202
+ protected :process_destination
203
+
204
+ def process_responses(responses)
205
+ if responses && !responses.empty?
206
+ logger.debug("Putting response #{responses.first.body} onto outgoing queue")
207
+ @connection.put(responses.shift.to_json) do
208
+ increment_messages_sent!
209
+ process_responses(responses)
210
+ end
211
+ else
212
+ logger.debug("No response.")
213
+ end
214
+ end
215
+
216
+ def status
217
+ {
218
+ :messages_received_count => messages_received_count,
219
+ :messages_sent_count => messages_sent_count,
220
+ :last_message_received => last_message_received,
221
+ :last_message_sent => last_message_sent
222
+ }
223
+ end
224
+
225
+ def increment_messages_sent!
226
+ @messages_sent_count += 1
227
+ @last_message_sent = Time.new
228
+ end
229
+
230
+ def increment_messages_received!
231
+ @messages_received_count += 1
232
+ @last_message_received = Time.new
233
+ end
234
+
235
+ end
@@ -0,0 +1,24 @@
1
+ desc "make executable"
2
+ directory.matches('/bin') do |dir|
3
+ dir.for('*') { |f|
4
+ f.append! <<-HERE_DOC
5
+ #!/usr/bin/env ruby
6
+
7
+ require 'rubygems'
8
+ if ENV['MESSED_HOME']
9
+ require File.join(ENV['MESSED_HOME'], 'lib', 'messed')
10
+ else
11
+ require 'messed'
12
+ end
13
+
14
+ require 'thor'
15
+ HERE_DOC
16
+
17
+ f.make_executable!
18
+ }
19
+ end
20
+
21
+ desc "set application name to #{options[:app_name]}"
22
+ files.all do |f|
23
+ f.gsub!('__APP_NAME__', options[:app_name].inspect)
24
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec'
2
+ require 'spec/rake/spectask'
3
+ task :spec => 'spec:all'
4
+ namespace(:spec) do
5
+ Spec::Rake::SpecTask.new(:all) do |t|
6
+ t.spec_opts ||= []
7
+ t.spec_opts << "-rubygems"
8
+ t.spec_opts << "--options" << "spec/spec.opts"
9
+ t.spec_files = FileList['spec/**/*_spec.rb']
10
+ end
11
+
12
+ end
@@ -0,0 +1,5 @@
1
+ # define your mappings here
2
+
3
+ #with 'hey you' do
4
+ # say 'hey hey'
5
+ #end
@@ -0,0 +1,3 @@
1
+ $root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
2
+
3
+ Messed::Tasks::Console.start
@@ -0,0 +1,3 @@
1
+ $root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
2
+
3
+ Messed::Tasks::Runner.start
@@ -0,0 +1,3 @@
1
+ $root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
2
+
3
+ Messed::Tasks::Status.start
@@ -0,0 +1,13 @@
1
+ class WebTask < Thor
2
+
3
+ method_options :detach => false
4
+ method_options :environment => "development"
5
+ def start
6
+
7
+
8
+
9
+ end
10
+
11
+ end
12
+
13
+ IncomingRunnerTask.start
@@ -0,0 +1,15 @@
1
+ queues.incoming.host = '127.0.0.1'
2
+ queues.incoming.port = 11300
3
+ queues.incoming.tube = 'incoming-tube'
4
+
5
+ queues.outgoing.host = '127.0.0.1'
6
+ queues.outgoing.port = 11300
7
+ queues.outgoing.tube = 'outgoing-tube'
8
+
9
+ # interfaces.search.adapter = :twitter_search
10
+ # interfaces.search.options[:fetch] = {:query => {'q' => 'love'}, :host => 'search.twitter.com', :path => 'search.json'}
11
+ # interfaces.search.options[:interval] = 30
12
+
13
+ # interfaces.twitter_sender.adapter = :twitter_sender
14
+ # interfaces.twitter_sender.options[:username] = 'username'
15
+ # interfaces.twitter_sender.options[:password] = 'password'
@@ -0,0 +1,2 @@
1
+ self.logger = ::Logger.new(STDOUT)
2
+ self.log_level = :debug
File without changes
File without changes
@@ -0,0 +1,12 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe "test" do
4
+
5
+ include MessedSpecHelper
6
+
7
+ it "should have a test" do
8
+ process('this is my message')
9
+ outgoing_messages.size.should == 1
10
+ outgoing_messages.first.body.should == "well, that was fun"
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ --colour
2
+ --format
3
+ specdoc
4
+ --loadby
5
+ mtime
6
+ --reverse
7
+ --backtrace
@@ -0,0 +1,44 @@
1
+ require 'rubygems'
2
+ begin
3
+ require 'messed'
4
+ rescue LoadError
5
+ if ENV['MESSED_HOME']
6
+ require File.join(ENV['MESSED_HOME'], 'lib', 'messed')
7
+ else
8
+ raise("no messed!")
9
+ end
10
+ end
11
+
12
+ class MessedSpecHolder
13
+
14
+ attr_accessor :booter, :outgoing_messages
15
+
16
+ def initialize
17
+ @booter = Messed::Booter.new(File.join(File.dirname(__FILE__), '..'))
18
+ end
19
+
20
+ def application
21
+ @booter.application
22
+ end
23
+
24
+ def process(message)
25
+ @outgoing_messages = application.process(application.message_class.new(message))
26
+ end
27
+
28
+ end
29
+
30
+
31
+
32
+ module MessedSpecHelper
33
+
34
+ Holder = MessedSpecHolder.new
35
+
36
+ def process(message)
37
+ Holder.process(message)
38
+ end
39
+
40
+ def outgoing_messages
41
+ Holder.outgoing_messages
42
+ end
43
+
44
+ end
@@ -0,0 +1,3 @@
1
+ with 'hey you' do
2
+ say 'hey hey'
3
+ end
@@ -0,0 +1,7 @@
1
+ with 'hey you' do
2
+ say 'hey hey'
3
+ end
4
+
5
+ otherwise do
6
+ say message
7
+ end