mediator 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.
- data/.autotest +63 -0
- data/.gitignore +17 -0
- data/Gemfile +2 -0
- data/README.md +81 -0
- data/Rakefile +4 -0
- data/lib/mediator/parser.rb +33 -0
- data/lib/mediator.rb +148 -0
- data/mediator.gemspec +15 -0
- data/test/mediator_parser_test.rb +80 -0
- data/test/mediator_test.rb +203 -0
- metadata +57 -0
data/.autotest
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require "autotest/restart"
|
2
|
+
|
3
|
+
Autotest.add_hook :initialize do |at|
|
4
|
+
at.testlib = "minitest/autorun"
|
5
|
+
|
6
|
+
# Autotest's defaults don't match our idiom, so we'll build the
|
7
|
+
# mappings by hand.
|
8
|
+
|
9
|
+
at.clear_mappings
|
10
|
+
|
11
|
+
# Changed tests always run themselves.
|
12
|
+
|
13
|
+
at.add_mapping %r{^test/.*_test.rb$} do |f, _|
|
14
|
+
[f]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Run corresponding unit tests if something in lib changes.
|
18
|
+
|
19
|
+
at.add_mapping %r{^(?:lib)/(.*)\.rb$} do |f, m|
|
20
|
+
["test/#{m[1]}_test.rb"]
|
21
|
+
end
|
22
|
+
|
23
|
+
at.add_exception ".autotest"
|
24
|
+
at.add_exception ".git"
|
25
|
+
at.add_exception "Gemfile"
|
26
|
+
at.add_exception "README.md"
|
27
|
+
at.add_exception "Rakefile"
|
28
|
+
at.add_exception "mediator.gemspec"
|
29
|
+
at.add_exception "pkg"
|
30
|
+
end
|
31
|
+
|
32
|
+
class Autotest
|
33
|
+
TESTFILES = Dir["test/*_test.rb"]
|
34
|
+
|
35
|
+
# Because MiniTest::Spec's generated class names (very
|
36
|
+
# understandably) can't map reliably to test files, try to guess a
|
37
|
+
# file by turning the describe block's class name into a file path
|
38
|
+
# and gradually making it more general until something matches.
|
39
|
+
|
40
|
+
def consolidate_failures failed
|
41
|
+
filters = new_hash_of_arrays
|
42
|
+
|
43
|
+
failed.each do |method, klass|
|
44
|
+
fragments = klass.sub(/Spec$/, "").
|
45
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
46
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
47
|
+
downcase.split "_"
|
48
|
+
|
49
|
+
until fragments.empty?
|
50
|
+
candidate = "test/#{fragments.join '_'}_test.rb"
|
51
|
+
|
52
|
+
if TESTFILES.include? candidate
|
53
|
+
filters[candidate] << method
|
54
|
+
break
|
55
|
+
end
|
56
|
+
|
57
|
+
fragments.pop
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
filters
|
62
|
+
end
|
63
|
+
end
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# Mediator
|
2
|
+
|
3
|
+
## Notes on Render
|
4
|
+
|
5
|
+
# taken from the old notation in a bunch of different models, just
|
6
|
+
# examples of shit that needs to work
|
7
|
+
|
8
|
+
def render! r
|
9
|
+
|
10
|
+
# from Account
|
11
|
+
|
12
|
+
if context.root?
|
13
|
+
r.key :color
|
14
|
+
r.key :key, self[:domain]
|
15
|
+
end
|
16
|
+
|
17
|
+
if subject.is? :sso
|
18
|
+
r.key :sso, private: sso_private
|
19
|
+
end
|
20
|
+
|
21
|
+
# from Album
|
22
|
+
|
23
|
+
if inside? artist
|
24
|
+
r.key :artist, id: artist.id, name: artist.name
|
25
|
+
end
|
26
|
+
|
27
|
+
# from Artist
|
28
|
+
|
29
|
+
r.array :albums
|
30
|
+
r.obj :contact
|
31
|
+
|
32
|
+
# from Collaborator
|
33
|
+
|
34
|
+
r.ids :tracks, tracks.active
|
35
|
+
r.id :pro # WAS: a.set :pro, pro.id if pro
|
36
|
+
|
37
|
+
# from Model
|
38
|
+
|
39
|
+
r.key :created, from: :created_at
|
40
|
+
end
|
41
|
+
|
42
|
+
## TODO
|
43
|
+
|
44
|
+
* Nested collections or objects, like `r.array :albums` or `r.obj
|
45
|
+
:contact` in the example above. Should create a new mediator stack
|
46
|
+
for each entry in the collection but somehow mark the current
|
47
|
+
mediator as the parent.
|
48
|
+
|
49
|
+
* For `r.ids`, just value.map(&:id). Should check for `_ids` shortcut
|
50
|
+
first though, but only if an explicit value isn't provided.
|
51
|
+
|
52
|
+
* For `r.id :pro`, should first check for `pro_id` and then
|
53
|
+
fall back on `pro.id`.
|
54
|
+
|
55
|
+
* Nested collections should always exist in rendered output even if
|
56
|
+
they're empty or missing.
|
57
|
+
|
58
|
+
* Benchmarks and micro-opts, esp. around object allocation.
|
59
|
+
|
60
|
+
## License (MIT)
|
61
|
+
|
62
|
+
Copyright 2011 Audiosocket (tech@audiosocket.com)
|
63
|
+
|
64
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
65
|
+
a copy of this software and associated documentation files (the
|
66
|
+
'Software'), to deal in the Software without restriction, including
|
67
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
68
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
69
|
+
permit persons to whom the Software is furnished to do so, subject to
|
70
|
+
the following conditions:
|
71
|
+
|
72
|
+
The above copyright notice and this permission notice shall be
|
73
|
+
included in all copies or substantial portions of the Software.
|
74
|
+
|
75
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
76
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
77
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
78
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
79
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
80
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
81
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
class Mediator
|
2
|
+
class Parser
|
3
|
+
attr_reader :data
|
4
|
+
attr_reader :mediator
|
5
|
+
|
6
|
+
def initialize mediator, data = {}
|
7
|
+
@data = data
|
8
|
+
@mediator = mediator
|
9
|
+
end
|
10
|
+
|
11
|
+
def get name
|
12
|
+
data[name] || data[name.to_s]
|
13
|
+
end
|
14
|
+
|
15
|
+
def has? name
|
16
|
+
!!get(name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def key name, options = nil, &block
|
20
|
+
selector = (options && options[:from]) || name
|
21
|
+
value ||= get(selector) || (options && options[:value])
|
22
|
+
|
23
|
+
return if value.nil? or value.respond_to?(:empty?) && value.empty?
|
24
|
+
|
25
|
+
value = block[value] if block_given?
|
26
|
+
key! name, value
|
27
|
+
end
|
28
|
+
|
29
|
+
def key! name, value
|
30
|
+
mediator.set name, value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/mediator.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require "mediator/parser"
|
2
|
+
|
3
|
+
# Helps translate an object to and from more primitive, untyped
|
4
|
+
# forms. Mediators should subclass and implement `parse` and `render`,
|
5
|
+
# or use the class-level helpers to declare the necessary
|
6
|
+
# transformations.
|
7
|
+
|
8
|
+
class Mediator
|
9
|
+
|
10
|
+
# This lambda takes a single argument, does nothing, and returns `nil`.
|
11
|
+
|
12
|
+
NOTHING = lambda { |_| nil }
|
13
|
+
|
14
|
+
# State information availble during `parse` and `render`. This is
|
15
|
+
# often an application-specific object that provides authentication
|
16
|
+
# and authorization data, but it can be just about anything.
|
17
|
+
|
18
|
+
attr_reader :context
|
19
|
+
|
20
|
+
# An optional parent mediator. Used during nested mediation: See
|
21
|
+
# `array`, `obj`, etc.
|
22
|
+
|
23
|
+
attr_reader :parent
|
24
|
+
|
25
|
+
# The subject of this mediation. A rich(er) domain object that needs
|
26
|
+
# to be translated back and forth.
|
27
|
+
|
28
|
+
attr_reader :subject
|
29
|
+
|
30
|
+
# Create a new mediator with a `subject` and a mediation
|
31
|
+
# `context`. If the context is a Mediator, it will be set as this
|
32
|
+
# instance's parent and its context will be reused.
|
33
|
+
|
34
|
+
def initialize subject, context = nil
|
35
|
+
@context = context
|
36
|
+
@subject = subject
|
37
|
+
|
38
|
+
if Mediator === context
|
39
|
+
@parent = @context
|
40
|
+
@context = @parent.context
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Is `subject` the subject of one of the ancestral mediators?
|
45
|
+
|
46
|
+
def inside? subject
|
47
|
+
parent && (parent.subject == subject || parent.inside?(subject))
|
48
|
+
end
|
49
|
+
|
50
|
+
# Is this mediator nested inside a `parent`?
|
51
|
+
|
52
|
+
def nested?
|
53
|
+
!!parent
|
54
|
+
end
|
55
|
+
|
56
|
+
# Folds, spindles, and mutilates `data`, then applies to `subject`
|
57
|
+
# and returns it. Subclasses should override `parse!` instead of
|
58
|
+
# this method.
|
59
|
+
|
60
|
+
def parse data
|
61
|
+
parse! Mediator::Parser.new(self, data)
|
62
|
+
subject
|
63
|
+
end
|
64
|
+
|
65
|
+
# The actual parse implementation. Subclasses should override and
|
66
|
+
# consistently call `super`. Default implementation is empty.
|
67
|
+
|
68
|
+
def parse! parser
|
69
|
+
end
|
70
|
+
|
71
|
+
# Create a more primitive representation of `subject`. Depending on
|
72
|
+
# app design and `context`, the output of `render` may not always be
|
73
|
+
# valid input to `parse`. Implement in subclasses.
|
74
|
+
|
75
|
+
def render
|
76
|
+
raise NotImplementedError, "Implement #{self.class.name}#render."
|
77
|
+
end
|
78
|
+
|
79
|
+
# Set `name` to `value` on `subject`. The default implementation
|
80
|
+
# calls a matching mutator method.
|
81
|
+
|
82
|
+
def set name, value
|
83
|
+
subject.send "#{name}=", setting(name, value)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Called when setting `name` to `value` on `subject`. Can be used to
|
87
|
+
# transform incoming values, e.g., trimming all strings. The default
|
88
|
+
# implementation returns `value` unchanged.
|
89
|
+
|
90
|
+
def setting name, value
|
91
|
+
value
|
92
|
+
end
|
93
|
+
|
94
|
+
# Find and instantiate a mediator for `subject` by consulting
|
95
|
+
# `map`. Returns `nil` if no mediator can be found. Inheritance is
|
96
|
+
# respected for mediators registered by class, so:
|
97
|
+
#
|
98
|
+
# A = Class.new
|
99
|
+
# B = Class.new A
|
100
|
+
# M = Class.new Mediator
|
101
|
+
#
|
102
|
+
# M.subject A
|
103
|
+
# Mediator.for B.new # => A
|
104
|
+
|
105
|
+
def self.for subject, context = nil
|
106
|
+
map.each do |criteria, mediator|
|
107
|
+
return mediator.new subject, context if criteria === subject
|
108
|
+
end
|
109
|
+
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
|
113
|
+
# An alias of `for`.
|
114
|
+
|
115
|
+
def self.[] subject, context = nil
|
116
|
+
self.for subject, context
|
117
|
+
end
|
118
|
+
|
119
|
+
# A Hash of mappings from subject to Mediator subclass.
|
120
|
+
|
121
|
+
def self.map
|
122
|
+
@@map
|
123
|
+
end
|
124
|
+
|
125
|
+
@@map = {}
|
126
|
+
|
127
|
+
# Register this Mediator subclass's interest in one or more subject
|
128
|
+
# classes. If more detailed selection behavior is necessary,
|
129
|
+
# `subject` can take a block instead. When the mediator for a
|
130
|
+
# subject is discovered with `Mediator.for` the given block will be
|
131
|
+
# passed the subject and can return `true` or `false`.
|
132
|
+
|
133
|
+
def self.subject *klasses, &block
|
134
|
+
raise "Only call subject on #{name} subclasses." if Mediator == self
|
135
|
+
|
136
|
+
if block_given?
|
137
|
+
unless klasses.empty?
|
138
|
+
raise ArgumentError, "Can't provide both classes and a block."
|
139
|
+
end
|
140
|
+
|
141
|
+
map[block] = self
|
142
|
+
end
|
143
|
+
|
144
|
+
klasses.each { |k| map[k] = self }
|
145
|
+
|
146
|
+
self
|
147
|
+
end
|
148
|
+
end
|
data/mediator.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.authors = ["Audiosocket"]
|
3
|
+
gem.email = ["tech@audiosocket.com"]
|
4
|
+
gem.description = "A go-between for models."
|
5
|
+
gem.summary = "Translates models to and from primitive representations."
|
6
|
+
gem.homepage = "https://github.com/audiosocket/mediator"
|
7
|
+
|
8
|
+
gem.files = `git ls-files`.split "\n"
|
9
|
+
gem.test_files = `git ls-files -- test/*`.split "\n"
|
10
|
+
gem.name = "mediator"
|
11
|
+
gem.require_paths = ["lib"]
|
12
|
+
gem.version = "0.0.0"
|
13
|
+
|
14
|
+
gem.required_ruby_version = ">= 1.9.2"
|
15
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require "mediator"
|
2
|
+
require "mediator/parser"
|
3
|
+
require "minitest/autorun"
|
4
|
+
require "ostruct"
|
5
|
+
|
6
|
+
describe Mediator::Parser do
|
7
|
+
before do
|
8
|
+
@subject = OpenStruct.new
|
9
|
+
@mediator = Mediator.new @subject
|
10
|
+
end
|
11
|
+
|
12
|
+
it "has data" do
|
13
|
+
p = Mediator::Parser.new :mediator, :data
|
14
|
+
assert_equal :data, p.data
|
15
|
+
end
|
16
|
+
|
17
|
+
it "has default data" do
|
18
|
+
assert_equal Hash.new, Mediator::Parser.new(:mediator).data
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "declaring keys explicitly" do
|
22
|
+
before do
|
23
|
+
@parser = Mediator::Parser.new @mediator,
|
24
|
+
emptystring: "", emptyarray: [], isnil: nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "sets unconditionally with key!" do
|
28
|
+
@parser.key! :foo, :bar
|
29
|
+
assert_equal :bar, @subject.foo
|
30
|
+
end
|
31
|
+
|
32
|
+
it "can pull from the options hash" do
|
33
|
+
@parser.key :foo, value: :bar
|
34
|
+
assert_equal :bar, @subject.foo
|
35
|
+
end
|
36
|
+
|
37
|
+
it "ignores empty values" do
|
38
|
+
@parser.key :emptystring
|
39
|
+
assert_nil @subject.emptystring
|
40
|
+
|
41
|
+
@parser.key :emptyarray
|
42
|
+
assert_nil @subject.emptyarray
|
43
|
+
end
|
44
|
+
|
45
|
+
it "ignores nil values" do
|
46
|
+
@parser.key :isnil
|
47
|
+
assert_nil @subject.isnil # heh
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "setting values from data" do
|
52
|
+
it "grabs from data like it's a Hash" do
|
53
|
+
p = Mediator::Parser.new @mediator, foo: "bar"
|
54
|
+
p.key :foo
|
55
|
+
|
56
|
+
assert_equal "bar", @subject.foo
|
57
|
+
end
|
58
|
+
|
59
|
+
it "works with strings and symbols" do
|
60
|
+
p = Mediator::Parser.new @mediator, "foo" => "bar"
|
61
|
+
p.key :foo
|
62
|
+
|
63
|
+
assert_equal "bar", @subject.foo
|
64
|
+
end
|
65
|
+
|
66
|
+
it "transforms values with a block" do
|
67
|
+
p = Mediator::Parser.new @mediator, foo: "bar"
|
68
|
+
p.key(:foo) { |d| d.upcase }
|
69
|
+
|
70
|
+
assert_equal "BAR", @subject.foo
|
71
|
+
end
|
72
|
+
|
73
|
+
it "can declaratively alias a name with :from" do
|
74
|
+
p = Mediator::Parser.new @mediator, quux: "bar"
|
75
|
+
p.key :foo, from: :quux
|
76
|
+
|
77
|
+
assert_equal "bar", @subject.foo
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require "mediator"
|
2
|
+
require "minitest/autorun"
|
3
|
+
require "ostruct"
|
4
|
+
|
5
|
+
describe Mediator do
|
6
|
+
before do
|
7
|
+
Mediator.map.clear
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "initialization" do
|
11
|
+
it "takes a subject and a context" do
|
12
|
+
m = Mediator.new :subject, :context
|
13
|
+
|
14
|
+
assert_equal :context, m.context
|
15
|
+
assert_equal :subject, m.subject
|
16
|
+
end
|
17
|
+
|
18
|
+
it "optionally takes a parent context" do
|
19
|
+
m = Mediator.new :s, :c
|
20
|
+
n = Mediator.new :t, m
|
21
|
+
|
22
|
+
assert_equal :c, n.context
|
23
|
+
assert_equal m, n.parent
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "nesting" do
|
28
|
+
it "is inside another mediator when a parent exists" do
|
29
|
+
m = Mediator.new :s, :c
|
30
|
+
|
31
|
+
refute m.nested?
|
32
|
+
assert Mediator.new(:s, m).nested?
|
33
|
+
end
|
34
|
+
|
35
|
+
it "can narrow inside? by checking subjects" do
|
36
|
+
m = Mediator.new :s, :c
|
37
|
+
n = Mediator.new :t, m
|
38
|
+
o = Mediator.new :u, n
|
39
|
+
|
40
|
+
assert n.inside? :s
|
41
|
+
assert o.inside? :s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "parsing" do
|
46
|
+
it "is a noop by default" do
|
47
|
+
m = Mediator.new :subject
|
48
|
+
m.parse :data
|
49
|
+
end
|
50
|
+
|
51
|
+
it "builds a Parser and delegates to parse!" do
|
52
|
+
c = Class.new Mediator do
|
53
|
+
def parse! parser
|
54
|
+
parser.key :foo
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
s = OpenStruct.new
|
59
|
+
m = c.new s
|
60
|
+
|
61
|
+
m.parse foo: :bar
|
62
|
+
assert_equal :bar, s.foo
|
63
|
+
end
|
64
|
+
|
65
|
+
it "always returns the subject" do
|
66
|
+
c = Class.new Mediator do
|
67
|
+
def self.parser
|
68
|
+
lambda { |p| :useless! }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
m = c.new :subject
|
73
|
+
assert_equal :subject, m.parse(:data)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it "will render at some point" do
|
78
|
+
ex = assert_raises NotImplementedError do
|
79
|
+
Mediator.new(:s).render
|
80
|
+
end
|
81
|
+
|
82
|
+
assert_equal "Implement Mediator#render.", ex.message
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "setting values on the subject" do
|
86
|
+
it "calls a setter by default" do
|
87
|
+
s = OpenStruct.new
|
88
|
+
m = Mediator.new s
|
89
|
+
|
90
|
+
m.set :foo, :bar
|
91
|
+
assert_equal :bar, s.foo
|
92
|
+
end
|
93
|
+
|
94
|
+
it "can transform incoming values" do
|
95
|
+
c = Class.new Mediator do
|
96
|
+
def setting name, value
|
97
|
+
case value
|
98
|
+
when String then value.upcase
|
99
|
+
else value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
s = OpenStruct.new
|
105
|
+
m = c.new s
|
106
|
+
|
107
|
+
m.set :foo, "bar"
|
108
|
+
assert_equal "BAR", s.foo
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe ".for" do
|
113
|
+
it "gets a mediator by class" do
|
114
|
+
c = Class.new(Mediator) { subject Symbol }
|
115
|
+
m = Mediator.for :foo
|
116
|
+
|
117
|
+
assert_instance_of c, m
|
118
|
+
end
|
119
|
+
|
120
|
+
it "gets a mediator for a subclass" do
|
121
|
+
x = Class.new
|
122
|
+
y = Class.new x
|
123
|
+
c = Class.new(Mediator) { subject x }
|
124
|
+
m = Mediator.for y.new
|
125
|
+
|
126
|
+
assert_instance_of c, m
|
127
|
+
end
|
128
|
+
|
129
|
+
it "gets a mediator by block eval" do
|
130
|
+
c = Class.new Mediator do
|
131
|
+
subject do |s|
|
132
|
+
"hello" == s
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
assert_instance_of c, Mediator.for("hello")
|
137
|
+
assert_nil Mediator.for "Hello!"
|
138
|
+
end
|
139
|
+
|
140
|
+
it "is also available as []" do
|
141
|
+
c = Class.new(Mediator) { subject Symbol }
|
142
|
+
assert_instance_of c, Mediator[:foo]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe ".subject" do
|
147
|
+
it "can only be called on subclasses" do
|
148
|
+
ex = assert_raises RuntimeError do
|
149
|
+
Mediator.subject
|
150
|
+
end
|
151
|
+
|
152
|
+
assert_equal "Only call subject on Mediator subclasses.", ex.message
|
153
|
+
end
|
154
|
+
|
155
|
+
it "can register a class" do
|
156
|
+
c = Class.new Mediator do
|
157
|
+
subject Symbol
|
158
|
+
end
|
159
|
+
|
160
|
+
assert_equal c, Mediator.map[Symbol]
|
161
|
+
end
|
162
|
+
|
163
|
+
it "can register multiple classes" do
|
164
|
+
c = Class.new Mediator do
|
165
|
+
subject String, Symbol
|
166
|
+
end
|
167
|
+
|
168
|
+
assert_equal c, Mediator.map[String]
|
169
|
+
assert_equal c, Mediator.map[Symbol]
|
170
|
+
end
|
171
|
+
|
172
|
+
it "can register with a block" do
|
173
|
+
c = Class.new Mediator do
|
174
|
+
subject do |s|
|
175
|
+
Symbol === s
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
b = Mediator.map.keys.first
|
180
|
+
refute_nil b
|
181
|
+
|
182
|
+
assert b[:foo]
|
183
|
+
refute b["bar"]
|
184
|
+
end
|
185
|
+
|
186
|
+
it "doesn't allow classes and a block to be mixed" do
|
187
|
+
ex = assert_raises ArgumentError do
|
188
|
+
Class.new Mediator do
|
189
|
+
subject String do
|
190
|
+
# ...
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
assert_equal "Can't provide both classes and a block.", ex.message
|
196
|
+
end
|
197
|
+
|
198
|
+
it "returns self" do
|
199
|
+
c = Class.new Mediator
|
200
|
+
assert_equal c, c.subject
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mediator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Audiosocket
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-09 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: A go-between for models.
|
15
|
+
email:
|
16
|
+
- tech@audiosocket.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .autotest
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- lib/mediator.rb
|
27
|
+
- lib/mediator/parser.rb
|
28
|
+
- mediator.gemspec
|
29
|
+
- test/mediator_parser_test.rb
|
30
|
+
- test/mediator_test.rb
|
31
|
+
homepage: https://github.com/audiosocket/mediator
|
32
|
+
licenses: []
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ! '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.9.2
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubyforge_project:
|
51
|
+
rubygems_version: 1.8.10
|
52
|
+
signing_key:
|
53
|
+
specification_version: 3
|
54
|
+
summary: Translates models to and from primitive representations.
|
55
|
+
test_files:
|
56
|
+
- test/mediator_parser_test.rb
|
57
|
+
- test/mediator_test.rb
|