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