mediator 0.0.1 → 0.1.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/README.md CHANGED
@@ -21,7 +21,7 @@ I sit between your domain model and the cold, cruel world.
21
21
 
22
22
  ## License (MIT)
23
23
 
24
- Copyright 2011 John Barnette (code@jbarnette.com)
24
+ Copyright 2011-2012 Audiosocket (tech@audiosocket.com)
25
25
 
26
26
  Permission is hereby granted, free of charge, to any person obtaining
27
27
  a copy of this software and associated documentation files (the
@@ -15,40 +15,71 @@ class Mediator
15
15
  (options && options[:value]) || data[selector] || data[selector.to_s]
16
16
  end
17
17
 
18
- def has? name
19
- !!get(name)
18
+ def has? name, options = nil
19
+ selector = (options && options[:from]) || name
20
+ (options && options.has_key?(:value)) || data.has_key?(selector) || data.has_key?(selector.to_s)
20
21
  end
21
22
 
22
23
  def id name, options = {}
23
24
  key "#{name}_id", options.merge(from: name)
24
25
  end
25
26
 
27
+ def ids name, options = {}
28
+ if name[-1] == "s" and !options[:from]
29
+ id_name = "#{name[0..-2]}_ids"
30
+ else
31
+ id_name = "#{name}_ids"
32
+ end
33
+
34
+ options[:from] ||= name
35
+
36
+ key id_name, options
37
+ end
38
+
26
39
  def key name, options = nil, &block
27
40
  if name[-1] == "?"
28
41
  name = name[0..-2].intern
29
42
  end
30
43
 
31
- value = get name, options
44
+ return unless has? name, options
32
45
 
46
+ value = get name, options
33
47
  return if empty? value, options
34
- mediator.set name, block ? block[value] : value
48
+
49
+ value = block ? block[value] : value
50
+
51
+ mediator.set name, value unless empty? value, options
35
52
  end
36
53
 
37
- def obj name, options = nil, &block
54
+ def many name, options = nil, &block
38
55
  data = get name, options
39
56
  subj = (options && options[:subject]) || mediator.get(name)
40
57
 
41
- return if empty? data, options or subj.nil?
58
+ data.map { |d| sub subj[data.index d], d, options, &block }.
59
+ reject { |v| empty? v, options }
60
+ end
42
61
 
43
- Mediator[subj, mediator].parse data
44
- block[subj] if block
62
+ def one name, options = nil, &block
63
+ data = get name, options
64
+ subj = (options && options[:subject]) || mediator.get(name)
45
65
 
46
- subj
66
+ sub subj, data, options, &block
47
67
  end
48
68
 
49
69
  def union name, options = nil, &block
50
70
  (options ||= {}).merge! value: self.data
51
- obj name, options, &block
71
+ one name, options, &block
72
+ end
73
+
74
+ private
75
+
76
+ def sub subj, data, options, &block
77
+ return if empty? data, options or subj.nil?
78
+
79
+ Mediator[subj, mediator].parse data
80
+ block[subj] if block
81
+
82
+ subj
52
83
  end
53
84
  end
54
85
  end
@@ -2,7 +2,7 @@ class Mediator
2
2
  class Processor
3
3
  def empty? value, options = nil
4
4
  !(options && options[:empty]) &&
5
- (value.nil? || value.respond_to?(:empty?) && value.empty?)
5
+ (value.nil? || (value.respond_to?(:empty?) && value.empty?))
6
6
  end
7
7
  end
8
8
  end
@@ -19,6 +19,18 @@ class Mediator
19
19
  key name, options.merge(from: "#{name}_id")
20
20
  end
21
21
 
22
+ def ids name, options = {}
23
+ unless options[:from]
24
+ if name[-1] == "s"
25
+ options = options.merge(from: "#{name[0..-2]}_ids")
26
+ else
27
+ options = options.merge(from: "#{name}_ids")
28
+ end
29
+ end
30
+
31
+ key name, options
32
+ end
33
+
22
34
  def key name, options = nil, &block
23
35
  if name[-1] == "?"
24
36
  (options ||= {})[:from] = name
@@ -28,26 +40,38 @@ class Mediator
28
40
  value = get name, options
29
41
  return if empty? value, options
30
42
 
31
- data[name] = block ? block[value] : value
43
+ value = block ? block[value] : value
44
+
45
+ data[name] = value unless empty? value, options
32
46
  end
33
47
 
34
- def obj name, options = nil, &block
48
+ def many name, options = nil, &block
35
49
  value = get name, options
36
- return if empty? value, options
50
+ data[name] = value.map { |v| sub v, options, &block }.
51
+ reject { |v| empty? v, options }
52
+ end
37
53
 
38
- if value
39
- rendered = Mediator[value, mediator].render
40
- munged = block ? block[rendered] : rendered
41
- merge = options && options[:merge]
54
+ def one name, options = nil, &block
55
+ value = get name, options
56
+ return if empty? value, options
57
+
58
+ value = sub value, options, &block
59
+ return if empty? value, options
42
60
 
43
- merge ? data.merge!(munged) : data[name] = munged
44
- munged
45
- end
61
+ options && options[:merge] ? data.merge!(value) : data[name] = value
46
62
  end
47
63
 
48
64
  def union name, options = nil, &block
49
65
  (options ||= {}).merge! merge: true
50
- obj name, options, &block
66
+ one name, options, &block
51
67
  end
68
+
69
+ private
70
+
71
+ def sub value, options, &block
72
+ rendered = Mediator[value, mediator].render
73
+ block ? block[rendered] : rendered
74
+ end
75
+
52
76
  end
53
77
  end
data/lib/mediator.rb CHANGED
@@ -60,19 +60,24 @@ class Mediator
60
60
  parent && (parent.subject == subject || parent.inside?(subject))
61
61
  end
62
62
 
63
- # Two-way mediation. Mediators whose parsing and rendering
64
- # operations are identical should override and consistently call
65
- # `super`. `mediator` will be `parser` or `renderer`. The default
66
- # implementation raises NotImplementedError.
67
-
68
- def mediate! mediator
69
- raise NotImplementedError
70
- end
71
-
72
63
  # Is this mediator nested inside a `parent`?
73
64
 
74
- def nested?
75
- !!parent
65
+ def nested? candidate = nil, &block
66
+ if candidate && block
67
+ raise Error, "Can't provide both a candidate and a block."
68
+ end
69
+
70
+ if !parent
71
+ false
72
+ elsif !candidate && !block
73
+ true
74
+ elsif candidate && (candidate === parent.subject)
75
+ true
76
+ elsif block && block[parent]
77
+ true
78
+ else
79
+ parent.nested? candidate, &block
80
+ end
76
81
  end
77
82
 
78
83
  # Called after rendering. Subclasses can override to transform raw
@@ -93,11 +98,10 @@ class Mediator
93
98
  end
94
99
 
95
100
  # The actual parse implementation. Subclasses should override and
96
- # consistently call `super`. The default implementation calls
97
- # `mediate!`.
101
+ # consistently call `super`.
98
102
 
99
103
  def parse! parser
100
- mediate! parser
104
+ raise NotImplementedError
101
105
  end
102
106
 
103
107
  # Construct a parser instance for `data`. The parser will be passed
@@ -119,11 +123,10 @@ class Mediator
119
123
  end
120
124
 
121
125
  # The actual render implementation. Subclasses should override and
122
- # consistently call `super`. The default implementation calls
123
- # `mediate!`.
126
+ # consistently call `super`.
124
127
 
125
128
  def render! renderer
126
- mediate! renderer
129
+ raise NotImplementedError
127
130
  end
128
131
 
129
132
  # Construct a renderer instance. The renderer will be passed to the
data/mediator.gemspec CHANGED
@@ -1,15 +1,15 @@
1
1
  Gem::Specification.new do |gem|
2
- gem.authors = ["John Barnette"]
3
- gem.email = ["code@jbarnette.com"]
2
+ gem.authors = ["Audiosocket"]
3
+ gem.email = ["tech@audiosocket.com"]
4
4
  gem.description = "A go-between for models."
5
5
  gem.summary = "Translates models to and from primitive representations."
6
- gem.homepage = "https://github.com/jbarnette/mediator"
6
+ gem.homepage = "https://github.com/audiosocket/mediator"
7
7
 
8
8
  gem.files = `git ls-files`.split "\n"
9
9
  gem.test_files = `git ls-files -- test/*`.split "\n"
10
10
  gem.name = "mediator"
11
11
  gem.require_paths = ["lib"]
12
- gem.version = "0.0.1"
12
+ gem.version = "0.1.0"
13
13
 
14
14
  gem.required_ruby_version = ">= 1.9.2"
15
15
  end
@@ -29,18 +29,58 @@ describe Mediator::Parser do
29
29
  end
30
30
  end
31
31
 
32
+ describe "ids" do
33
+ it "translates name to subject.name_ids" do
34
+ p = Mediator::Parser.new @mediator, foo: [5, 6, 7]
35
+
36
+ p.ids :foo
37
+ assert_equal [5, 6, 7], @subject.foo_ids
38
+ end
39
+
40
+ it "removes plurial" do
41
+ p = Mediator::Parser.new @mediator, foos: [5, 6, 7]
42
+
43
+ p.ids :foos
44
+ assert_equal [5, 6, 7], @subject.foo_ids
45
+ end
46
+
47
+ it "can be clever with plurial if told to" do
48
+ p = Mediator::Parser.new @mediator, boxen: [5, 6, 7]
49
+
50
+ p.ids :box, from: :boxen
51
+ assert_equal [5, 6, 7], @subject.box_ids
52
+ end
53
+ end
54
+
32
55
  describe "key" do
33
56
  before do
34
- @parser = Mediator::Parser.new @mediator,
57
+ @data = {
35
58
  emptystring: "", emptyarray: [], isnil: nil,
36
- predicate: true
59
+ somevalue: :gni, predicate: true, othernil: nil
60
+ }
61
+ @parser = Mediator::Parser.new @mediator, @data
62
+ end
63
+
64
+ it "parses some values" do
65
+ @parser.key :somevalue
66
+
67
+ assert_equal :gni, @subject.somevalue
68
+ end
69
+
70
+ it "sets unconditionally with empty: true and data holds an empty value for that key." do
71
+ @subject.othernil = :not_nil
72
+
73
+ assert @data.has_key?(:othernil)
74
+ @parser.key :othernil, empty: true
75
+ assert_nil @subject.othernil
37
76
  end
38
77
 
39
- it "sets unconditionally with empty: true" do
78
+ it "does not touch a key with empty: true when data does not have that key defined." do
40
79
  @subject.foo = :foo
41
80
 
81
+ refute @data.has_key?(:foo)
42
82
  @parser.key :foo, empty: true
43
- assert_nil @subject.foo
83
+ assert_equal :foo, @subject.foo
44
84
  end
45
85
 
46
86
  it "removes trailing '?' from predicates" do
@@ -48,7 +88,6 @@ describe Mediator::Parser do
48
88
  assert @subject.predicate
49
89
  end
50
90
 
51
-
52
91
  it "can pull from the options hash" do
53
92
  @parser.key :foo, value: :bar
54
93
  assert_equal :bar, @subject.foo
@@ -66,6 +105,11 @@ describe Mediator::Parser do
66
105
  @parser.key :isnil
67
106
  assert_nil @subject.isnil # heh
68
107
  end
108
+
109
+ it "ignores nil or empty values returned by blocks" do
110
+ @parser.key(:somevalue) { |p| nil }
111
+ assert_nil @subject.foo # heh
112
+ end
69
113
  end
70
114
 
71
115
  describe "key with actual data" do
@@ -98,7 +142,7 @@ describe Mediator::Parser do
98
142
  end
99
143
  end
100
144
 
101
- describe "obj" do
145
+ describe "one" do
102
146
  before do
103
147
  Top = Class.new OpenStruct
104
148
  Nest = Class.new OpenStruct
@@ -108,7 +152,7 @@ describe Mediator::Parser do
108
152
 
109
153
  def parse! p
110
154
  p.key :foo
111
- p.obj :nest
155
+ p.one :nest
112
156
  end
113
157
  end
114
158
 
@@ -137,6 +181,41 @@ describe Mediator::Parser do
137
181
  end
138
182
  end
139
183
 
184
+ describe "many" do
185
+ before do
186
+ Many = Class.new OpenStruct
187
+ Nested = Class.new OpenStruct
188
+
189
+ Class.new Mediator do
190
+ accept Many
191
+
192
+ def parse! p
193
+ p.many :nest
194
+ end
195
+ end
196
+
197
+ Class.new Mediator do
198
+ accept Nested
199
+
200
+ def parse! p
201
+ p.key :baz
202
+ end
203
+ end
204
+ end
205
+
206
+ it "delegates to an array of nested mediator" do
207
+ s = Many.new
208
+ s.nest = [ Nested.new, Nested.new ]
209
+
210
+ m = Mediator[s]
211
+ d = { nest: [ { baz: "baz!" }, { baz: "blup?" } ] }
212
+
213
+ m.parse d
214
+
215
+ assert_equal d[:nest].map { |v| v[:baz] }, s.nest.map { |v| v.baz }
216
+ end
217
+ end
218
+
140
219
  describe "union" do
141
220
  it "uses the same data as its parent" do
142
221
  First = Class.new OpenStruct
@@ -12,6 +12,144 @@ describe Mediator::Renderer do
12
12
  assert_equal Hash.new, Mediator::Renderer.new(nil).data
13
13
  end
14
14
 
15
+ describe "id" do
16
+ it "grabs an id" do
17
+ c = Class.new Mediator do
18
+ def render! r
19
+ r.id :foo
20
+ end
21
+ end
22
+
23
+ x = OpenStruct.new foo_id: 5
24
+ m = c.new x
25
+ r = { foo: 5 }
26
+
27
+ assert_equal r, m.render
28
+ end
29
+ end
30
+
31
+ describe "ids" do
32
+ it "grabs an array of ids" do
33
+ c = Class.new Mediator do
34
+ def render! r
35
+ r.ids :foo
36
+ end
37
+ end
38
+
39
+ x = OpenStruct.new foo_ids: [5, 6, 7]
40
+ m = c.new x
41
+ r = { foo: [5, 6, 7] }
42
+
43
+ assert_equal r, m.render
44
+ end
45
+
46
+ it "removes plurial" do
47
+ c = Class.new Mediator do
48
+ def render! r
49
+ r.ids :foos
50
+ end
51
+ end
52
+
53
+ x = OpenStruct.new foo_ids: [5, 6, 7]
54
+ m = c.new x
55
+ r = { foos: [5, 6, 7] }
56
+
57
+ assert_equal r, m.render
58
+ end
59
+
60
+ it "can be clever with plurial if told to" do
61
+ c = Class.new Mediator do
62
+ def render! r
63
+ r.ids :boxen, from: "box_ids"
64
+ end
65
+ end
66
+
67
+ x = OpenStruct.new box_ids: [5, 6, 7]
68
+ m = c.new x
69
+ r = { boxen: [5, 6, 7] }
70
+
71
+ assert_equal r, m.render
72
+ end
73
+ end
74
+
75
+ describe "many" do
76
+ it "grabs a collection from the subject" do
77
+ c = Class.new Mediator do
78
+ def render! r
79
+ r.many :foo
80
+ end
81
+ end
82
+
83
+ d = Class.new Mediator do
84
+ accept OpenStruct
85
+
86
+ def render! r
87
+ r.key :bar
88
+ end
89
+ end
90
+
91
+ x = OpenStruct.new bar: "gni"
92
+ y = OpenStruct.new bar: "gno"
93
+ s = OpenStruct.new foo: [x, y]
94
+ m = c.new s
95
+ d = m.render
96
+
97
+ r = { foo: [ { bar: "gni" }, { bar: "gno" } ] }
98
+ assert_equal r, d
99
+ end
100
+
101
+ it "can alter values" do
102
+ c = Class.new Mediator do
103
+ def render! r
104
+ r.many(:foo) { |v| { bar: v[:bar].upcase } }
105
+ end
106
+ end
107
+
108
+ d = Class.new Mediator do
109
+ accept OpenStruct
110
+
111
+ def render! r
112
+ r.key :bar
113
+ end
114
+ end
115
+
116
+ x = OpenStruct.new bar: "gni"
117
+ y = OpenStruct.new bar: "gno"
118
+ s = OpenStruct.new foo: [x, y]
119
+ m = c.new s
120
+ d = m.render
121
+
122
+ r = { foo: [ { bar: "GNI" }, { bar: "GNO" } ] }
123
+ assert_equal r, d
124
+ end
125
+
126
+ it "removes empty values" do
127
+ c = Class.new Mediator do
128
+ def render! r
129
+ r.many :foo
130
+ end
131
+ end
132
+
133
+ d = Class.new Mediator do
134
+ accept OpenStruct
135
+
136
+ def render! r
137
+ r.key :bar if subject.bar == "gni"
138
+ end
139
+ end
140
+
141
+ x = OpenStruct.new bar: "gni"
142
+ y = OpenStruct.new bar: "gno"
143
+ s = OpenStruct.new foo: [x, y]
144
+ m = c.new s
145
+ d = m.render
146
+
147
+ r = { foo: [ { bar: "gni" } ] }
148
+ assert_equal r, d
149
+ end
150
+ end
151
+
152
+
15
153
  describe "key" do
16
154
  it "grabs the value from the subject" do
17
155
  c = Class.new Mediator do
@@ -55,6 +193,20 @@ describe Mediator::Renderer do
55
193
  assert_equal Hash.new, d
56
194
  end
57
195
 
196
+ it "ignores nil or empty values returned by blocks" do
197
+ c = Class.new Mediator do
198
+ def render! r
199
+ r.key(:foo) { |p| nil }
200
+ end
201
+ end
202
+
203
+ s = OpenStruct.new foo: "bar"
204
+ m = c.new s
205
+ d = m.render
206
+
207
+ assert_equal Hash.new, d
208
+ end
209
+
58
210
  it "optionally allows empty values" do
59
211
  c = Class.new Mediator do
60
212
  def render! r
@@ -114,11 +266,11 @@ describe Mediator::Renderer do
114
266
  end
115
267
  end
116
268
 
117
- describe "obj" do
269
+ describe "one" do
118
270
  it "allows mediation of an associated object" do
119
271
  c = Class.new Mediator do
120
272
  def render! r
121
- r.obj :foo
273
+ r.one :foo
122
274
  end
123
275
  end
124
276
 
@@ -32,6 +32,34 @@ describe Mediator do
32
32
  assert Mediator.new(:s, m).nested?
33
33
  end
34
34
 
35
+ it "can test if it is nested inside a specific parent's subject." do
36
+ m = OpenStruct.new bar: "gni"
37
+ n = Mediator.new m, :t
38
+ o = Mediator.new :u, n
39
+
40
+ refute n.nested? m
41
+ assert o.nested? m
42
+ assert o.nested? OpenStruct
43
+ end
44
+
45
+ it "can test up in inheritance tree." do
46
+ m = OpenStruct.new bar: "gni"
47
+ n = Mediator.new m, :t
48
+ o = Mediator.new :u, n
49
+ v = Mediator.new :u, o
50
+
51
+ assert v.nested? m
52
+ end
53
+
54
+ it "accepts an arbitrary block to test against parent." do
55
+ m = OpenStruct.new bar: "gni"
56
+ n = Mediator.new m, :t
57
+ o = Mediator.new :u, n
58
+
59
+ refute o.nested? { |p| p.subject.bar == "gno" }
60
+ assert o.nested? { |p| p.subject.bar == "gni" }
61
+ end
62
+
35
63
  it "can narrow inside? by checking subjects" do
36
64
  m = Mediator.new :s, :c
37
65
  n = Mediator.new :t, m
@@ -65,20 +93,6 @@ describe Mediator do
65
93
  assert_equal :bar, s.foo
66
94
  end
67
95
 
68
- it "falls back on mediate!" do
69
- c = Class.new Mediator do
70
- def mediate! m
71
- m.key :foo
72
- end
73
- end
74
-
75
- s = OpenStruct.new
76
- m = c.new s
77
-
78
- m.parse foo: :bar
79
- assert_equal :bar, s.foo
80
- end
81
-
82
96
  it "always returns the subject" do
83
97
  c = Class.new Mediator do
84
98
  def parse! p
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mediator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - John Barnette
8
+ - Audiosocket
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-17 00:00:00.000000000Z
12
+ date: 2012-05-17 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: A go-between for models.
15
15
  email:
16
- - code@jbarnette.com
16
+ - tech@audiosocket.com
17
17
  executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files: []
@@ -33,7 +33,7 @@ files:
33
33
  - test/mediator_parser_test.rb
34
34
  - test/mediator_renderer_test.rb
35
35
  - test/mediator_test.rb
36
- homepage: https://github.com/jbarnette/mediator
36
+ homepage: https://github.com/audiosocket/mediator
37
37
  licenses: []
38
38
  post_install_message:
39
39
  rdoc_options: []