mediator 0.0.1 → 0.1.0

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