transporter 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ doc/*
2
+ dist/*
3
+ tmp/*
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2008-2009 Nicolas Sanguinetti
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,65 @@
1
+ = Transporter
2
+
3
+ Deliver packages in multiple ways simultaneously (email, jabber, campfire, irc,
4
+ etc.)
5
+
6
+ == API
7
+
8
+ require "transporter"
9
+
10
+ module Transporter
11
+ class Email < Service
12
+ validate_config do |config|
13
+ config.has_keys :from, :to, :host, :user, :password, :port, :auth
14
+ config.key_is_one_of :auth, %w(plain auth some other)
15
+ [:to, :from].each do |key|
16
+ config.key_matches key, /--some complicated email regexp--/
17
+ end
18
+ end
19
+
20
+ def deliver(message)
21
+ # Send your email
22
+ #
23
+ # In this method you have available `message.short` (usable for short
24
+ # messages such as twitter, or email subjects) and `message.full`
25
+ # usable for longer chunks of text, as an email body.
26
+ #
27
+ # And you have access to `config`, where all your pre-validated config
28
+ # values live (including default values set on the class, this hash is
29
+ # a merged representations of te two.
30
+ end
31
+ end
32
+
33
+ register :email, Email
34
+ end
35
+
36
+ == How to use
37
+
38
+ You probably want one of the child projects of this one, where the different
39
+ implementations provide you with specific implementations. However, the way to
40
+ use this is as follows:
41
+
42
+ Transporter.deliver(
43
+ :message => {
44
+ :short => "cuack!",
45
+ :full => "double cuack"
46
+ },
47
+ :using => {
48
+ :email => {
49
+ :to => "...", :from => "...", ...
50
+ },
51
+ :jabber => {
52
+ :to => "...", :from => "...", ...
53
+ }
54
+ }
55
+
56
+ Where each key of the `:using` hash depends on what implementations you loaded.
57
+ (`Transporter::Email`, `Transporter::Jabber`, etc). Refer to their specific
58
+ documentations for the full list of configuration values in each.
59
+
60
+ The `:short` message is used in messages like twitter, IM, or as an email
61
+ subject. The `:full` message is used
62
+
63
+ == List of implementations
64
+
65
+ * Example
@@ -0,0 +1,25 @@
1
+ require "rake/testtask"
2
+
3
+ begin
4
+ require "hanna/rdoctask"
5
+ rescue LoadError
6
+ require "rake/rdoctask"
7
+ end
8
+
9
+ Rake::RDocTask.new do |rd|
10
+ rd.main = "README"
11
+ rd.title = "API Documentation for Transporter"
12
+ rd.rdoc_files.include("README.rdoc", "LICENSE", "lib/**/*.rb")
13
+ rd.rdoc_dir = "doc"
14
+ end
15
+
16
+ begin
17
+ require "mg"
18
+ MG.new("transporter.gemspec")
19
+ rescue LoadError
20
+ end
21
+
22
+ Rake::TestTask.new
23
+
24
+ desc "Default: run tests"
25
+ task :default => :test
@@ -0,0 +1,23 @@
1
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__))
2
+
3
+ require "ninja"
4
+ require "transporter/package"
5
+ require "transporter/service"
6
+
7
+ module Transporter
8
+ def self.deliver(package)
9
+ Package.new(package).deliver
10
+ end
11
+
12
+ def self.register(name, service)
13
+ services[name] = service
14
+ end
15
+
16
+ def self.load_service(service)
17
+ services.fetch(service)
18
+ end
19
+
20
+ def self.services
21
+ @services ||= {}
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ module Transporter
2
+ class Package
3
+ include Ninja
4
+
5
+ attr_reader :short, :full
6
+
7
+ def initialize(package)
8
+ message = package.fetch(:message)
9
+ @short = message.fetch(:short)
10
+ @full = message.fetch(:full)
11
+ @services = package.fetch(:using)
12
+ end
13
+
14
+ def deliver
15
+ delivery_services.each do |service|
16
+ in_background { service.deliver(self) }
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def delivery_services
23
+ @services.map do |service, config|
24
+ Transporter.load_service(service).new(config)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ require "transporter/service/validations"
2
+
3
+ module Transporter
4
+ class Service
5
+ include Validations
6
+
7
+ class << self
8
+ attr_accessor :default_config
9
+ end
10
+
11
+ self.default_config = {}
12
+
13
+ attr_reader :config
14
+
15
+ def initialize(config)
16
+ @config = (self.class.default_config || {}).merge(config)
17
+ raise TypeError, config_errors unless valid_config?(config)
18
+ end
19
+
20
+ def deliver(message)
21
+ raise NotImplementedError, "Please implement this method on your service"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,70 @@
1
+ module Transporter
2
+ class Service
3
+ module Validations
4
+ def self.included(service)
5
+ service.extend ClassMethods
6
+ end
7
+
8
+ def config_errors
9
+ self.class.validator.errors
10
+ end
11
+
12
+ def valid_config?(config)
13
+ self.class.validator.valid?(config)
14
+ end
15
+
16
+ module ClassMethods
17
+ def validator(&block)
18
+ @validator ||= Validator.new(&block)
19
+ end
20
+ alias_method :validate_config, :validator
21
+ end
22
+
23
+ class Validator
24
+ attr_reader :errors
25
+
26
+ def initialize(&block)
27
+ @validations = Hash.new {|h,k| h[k] = [] }
28
+ @errors = Hash.new {|h,k| h[k] = [] }
29
+ block.call(self) if block
30
+ end
31
+
32
+ def has_keys(*keys)
33
+ keys.each do |key|
34
+ @validations[key] << lambda do |config|
35
+ config.has_key?(key) or raise TypeError, "config must include '#{key}', but does not"
36
+ end
37
+ end
38
+ end
39
+
40
+ def key_matches(key, format)
41
+ @validations[key] << lambda do |config|
42
+ config[key] =~ format or raise TypeError, "config '#{key}' must match '#{format}'"
43
+ end
44
+ end
45
+
46
+ def key_is_one_of(key, values)
47
+ @validations[key] << lambda do |config|
48
+ values.include? config[key] or raise TypeError, "config '#{key}' must be one of '#{values.join(", ")}'"
49
+ end
50
+ end
51
+
52
+ def valid?(config)
53
+ errors.clear
54
+
55
+ @validations.each do |key, validation_list|
56
+ validation_list.each do |validation|
57
+ begin
58
+ validation.call(config)
59
+ rescue TypeError => e
60
+ errors[key] << e.message
61
+ end
62
+ end
63
+ end
64
+
65
+ errors.empty?
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,58 @@
1
+ require "test/unit"
2
+ require "contest"
3
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/transporter")
4
+
5
+ begin
6
+ require "redgreen"
7
+ rescue LoadError
8
+ end
9
+
10
+ if ENV["DEBUG"]
11
+ require "ruby-debug"
12
+ else
13
+ def debugger
14
+ puts "Run your tests with DEBUG=1 to use the debugger"
15
+ end
16
+ end
17
+
18
+ module Transporter
19
+ def self.test_message_log
20
+ @test_message_log ||= []
21
+ end
22
+
23
+ class TestService < Service
24
+ validate_config do |config|
25
+ config.has_keys :foo, :bar
26
+ config.key_matches :foo, /^\d+$/
27
+ config.key_is_one_of :baz, ["one", "two", "three"]
28
+ end
29
+
30
+ def deliver(message)
31
+ Transporter.test_message_log << {
32
+ :short => message.short,
33
+ :full => message.full
34
+ }
35
+ end
36
+ end
37
+ register :test, TestService
38
+
39
+ class TestCase < Test::Unit::TestCase
40
+ setup { Transporter.test_message_log.clear }
41
+
42
+ def assert_has_short_message(message)
43
+ if Transporter.test_message_log.detect {|m| message == m[:short] }
44
+ assert true
45
+ else
46
+ flunk
47
+ end
48
+ end
49
+
50
+ def assert_has_full_message(message)
51
+ if Transporter.test_message_log.detect {|m| message == m[:full] }
52
+ assert true
53
+ else
54
+ flunk
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/test_helper")
2
+
3
+ class TestTransporter < Transporter::TestCase
4
+ def valid_message
5
+ {
6
+ :message => {
7
+ :short => "short message",
8
+ :full => "full message"
9
+ },
10
+ :using => {
11
+ :test => {
12
+ :foo => "1234",
13
+ :bar => "cuack",
14
+ :baz => "two"
15
+ }
16
+ }
17
+ }
18
+ end
19
+
20
+ test "delivers messages to the specified recipients" do
21
+ Transporter.deliver(valid_message)
22
+
23
+ assert_has_short_message "short message"
24
+ assert_has_full_message "full message"
25
+ end
26
+
27
+ test "raises TypeError when passing an invalid config for the Service" do
28
+ message = valid_message
29
+ message[:using][:test][:foo] = nil
30
+
31
+ assert_raises TypeError do
32
+ Transporter.deliver(message)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,39 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "transporter"
3
+ s.version = "0.1"
4
+ s.date = "2009-08-10"
5
+
6
+ s.description = "Deliver packages in multiple ways simultaneously (email, jabber, campfire, irc, etc.)"
7
+ s.summary = "Easily send messages using multiple communication channels"
8
+ s.homepage = "http://github.com/foca/Transporter"
9
+
10
+ s.authors = ["Nicolás Sanguinetti"]
11
+ s.email = "contacto@nicolassanguinetti.info"
12
+
13
+ s.require_paths = ["lib"]
14
+ s.rubyforge_project = "transporter"
15
+ s.has_rdoc = true
16
+ s.rubygems_version = "1.3.1"
17
+
18
+ s.add_dependency "ninja"
19
+
20
+ if s.respond_to?(:add_development_dependency)
21
+ s.add_development_dependency "sr-mg"
22
+ s.add_development_dependency "contest"
23
+ s.add_development_dependency "redgreen"
24
+ end
25
+
26
+ s.files = %w[
27
+ .gitignore
28
+ LICENSE
29
+ README.rdoc
30
+ Rakefile
31
+ transporter.gemspec
32
+ lib/transporter.rb
33
+ lib/transporter/package.rb
34
+ lib/transporter/service.rb
35
+ lib/transporter/service/validations.rb
36
+ test/test_helper.rb
37
+ test/test_transporter.rb
38
+ ]
39
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: transporter
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - "Nicol\xC3\xA1s Sanguinetti"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-10 00:00:00 -03:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ninja
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: sr-mg
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: contest
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: redgreen
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ description: Deliver packages in multiple ways simultaneously (email, jabber, campfire, irc, etc.)
56
+ email: contacto@nicolassanguinetti.info
57
+ executables: []
58
+
59
+ extensions: []
60
+
61
+ extra_rdoc_files: []
62
+
63
+ files:
64
+ - .gitignore
65
+ - LICENSE
66
+ - README.rdoc
67
+ - Rakefile
68
+ - transporter.gemspec
69
+ - lib/transporter.rb
70
+ - lib/transporter/package.rb
71
+ - lib/transporter/service.rb
72
+ - lib/transporter/service/validations.rb
73
+ - test/test_helper.rb
74
+ - test/test_transporter.rb
75
+ has_rdoc: true
76
+ homepage: http://github.com/foca/Transporter
77
+ licenses: []
78
+
79
+ post_install_message:
80
+ rdoc_options: []
81
+
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ version:
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ version:
96
+ requirements: []
97
+
98
+ rubyforge_project: transporter
99
+ rubygems_version: 1.3.4
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: Easily send messages using multiple communication channels
103
+ test_files: []
104
+