proxy_party 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
File without changes
data/README.textile ADDED
@@ -0,0 +1,128 @@
1
+ h1. Proxy Party
2
+
3
+ Greatly facilitates adding proxies through the proxy method_missing pattern.
4
+ Can now also dynamically add proxy methods and use other amazing meta strategies!
5
+
6
+ h2. Install
7
+
8
+ @$ gem install party_proxy@
9
+
10
+ h2. Use
11
+
12
+ @require 'party_proxy'@
13
+
14
+ h2. Latest news
15
+
16
+ Now supports renaming of proxy method so you can avoid method name collisions!
17
+
18
+ h2. TODO
19
+
20
+ Major DRYing up needed. Currently a lot of code duplication :O
21
+
22
+ h2. Usage
23
+
24
+ <pre>
25
+ class State
26
+ attr_accessor :name
27
+
28
+ def initialize(name)
29
+ @name = name
30
+ end
31
+ end
32
+
33
+ class Info
34
+ attr_accessor :text
35
+
36
+ def initialize(text)
37
+ @text = text
38
+ end
39
+ end
40
+
41
+ module Party
42
+ class Subject
43
+ # proxy state and info objects to make their methods
44
+ # directly accessible from subject objects
45
+ proxy :state, :info
46
+
47
+ def initialize(name)
48
+ @state = State.new name
49
+ @info = Info.new 'hello'
50
+ end
51
+ end
52
+ end
53
+ </pre>
54
+
55
+ <pre>
56
+ describe Party::Proxy do
57
+ describe '#proxy' do
58
+ it "proxies state and info so it can call name directly on subject" do
59
+ subject = Party::Subject.new 'kristian'
60
+ subject.name.should == 'kristian'
61
+ end
62
+ end
63
+
64
+ describe '#proxy_for' do
65
+ it "proxies speak_it! on mic" do
66
+ subject = Party::Subject.new 'kristian'
67
+ subject.mic = Mic.new 'hello'
68
+ Party::Subject.proxy_for :mic, :speak_it!
69
+
70
+ subject.proxy_for :mic, :speak_it!
71
+
72
+ subject.speak_it!.should == 'hello'
73
+ end
74
+
75
+ it "proxies speak_it! as speak_up! on mic" do
76
+ subject = Party::Subject.new 'kristian'
77
+ subject.mic = Mic.new 'hello'
78
+ Party::Subject.proxy_for :mic, :rename => {:speak_it! => :speak_up!}
79
+ subject.speak_up!.should == 'hello'
80
+ end
81
+ end
82
+
83
+ describe '#proxy_accessor_for' do
84
+ it "proxies speak accessor methods on mic" do
85
+ subject = Party::Subject.new 'kristian'
86
+ subject.mic = Mic.new 'hello'
87
+ subject.proxy_accessors_for :mic, :speak
88
+ subject.speak = 'do it!'
89
+ subject.speak.should == 'do it!'
90
+ end
91
+
92
+ it "proxies speak accessor method on mic as yell" do
93
+ subject = Party::Subject.new 'kristian'
94
+ subject.mic = Mic.new 'hello'
95
+ subject.proxy_accessors_for :mic, :rename => {:speak => :yell}
96
+ subject.yell = 'do it!'
97
+ subject.yell.should == 'do it!'
98
+ end
99
+ end
100
+
101
+ describe '#named_proxies' do
102
+ it "proxies select :mic and :state methods" do
103
+ subject = Party::Subject.new 'kristian'
104
+ subject.mic = Mic.new 'hello'
105
+ subject.named_proxies :mic => :speak, :state => :name
106
+ subject.speak = 'do it!'
107
+ subject.speak.should == 'do it!'
108
+
109
+ subject.name = 'kris'
110
+ subject.name.should == 'kris'
111
+ end
112
+ end
113
+ end
114
+ </pre>
115
+
116
+ h2. Note on Patches/Pull Requests
117
+
118
+ * Fork the project.
119
+ * Make your feature addition or bug fix.
120
+ * Add tests for it. This is important so I don't break it in a
121
+ future version unintentionally.
122
+ * Commit, do not mess with rakefile, version, or history.
123
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
124
+ * Send me a pull request. Bonus points for topic branches.
125
+
126
+ h2. Copyright
127
+
128
+ Copyright (c) 2010 Kristian Mandrup. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rubygems'
2
+ require 'psych'
2
3
  require 'rake'
3
4
 
4
5
  begin
@@ -10,7 +11,10 @@ begin
10
11
  gem.email = "kmandrup@gmail.com"
11
12
  gem.homepage = "http://github.com/kristianmandrup/proxy_party"
12
13
  gem.authors = ["Kristian Mandrup"]
13
- # gem.add_development_dependency "rspec", ">= 1.2.9"
14
+
15
+ gem.add_dependency "sugar-high", ">= 0.3.5"
16
+ gem.add_development_dependency "rspec", ">= 2.4.0"
17
+
14
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
19
  end
16
20
  Jeweler::GemcutterTasks.new
@@ -18,28 +22,3 @@ rescue LoadError
18
22
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
23
  end
20
24
 
21
- # require 'spec/rake/spectask'
22
- # Spec::Rake::SpecTask.new(:spec) do |spec|
23
- # spec.libs << 'lib' << 'spec'
24
- # spec.spec_files = FileList['spec/**/*_spec.rb']
25
- # end
26
- #
27
- # Spec::Rake::SpecTask.new(:rcov) do |spec|
28
- # spec.libs << 'lib' << 'spec'
29
- # spec.pattern = 'spec/**/*_spec.rb'
30
- # spec.rcov = true
31
- # end
32
- #
33
- # task :spec => :check_dependencies
34
- #
35
- # task :default => :spec
36
- #
37
- # require 'rake/rdoctask'
38
- # Rake::RDocTask.new do |rdoc|
39
- # version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
- #
41
- # rdoc.rdoc_dir = 'rdoc'
42
- # rdoc.title = "proxy_party #{version}"
43
- # rdoc.rdoc_files.include('README*')
44
- # rdoc.rdoc_files.include('lib/**/*.rb')
45
- # end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.1
data/lib/proxy_party.rb CHANGED
@@ -1,34 +1,346 @@
1
+ require 'sugar-high/array'
2
+ require 'sugar-high/kind_of'
3
+ require 'sugar-high/arguments'
4
+
1
5
  module Party
2
- module Proxy
6
+ module Proxy
7
+ class Factory
8
+ attr_reader :create_method, :klass
9
+
10
+ def initialize klass, create_method = nil
11
+ @klass = klass
12
+ @create_method = create_method
13
+ end
14
+
15
+ def create
16
+ create_method ? klass.send(create_method) : klass.new
17
+ end
18
+ end
3
19
 
4
20
  def self.included(base)
5
21
  base.extend ClassMethods
22
+ base.send :include, InstanceMethods
23
+ end
24
+
25
+ module InstanceMethods
26
+ attr_accessor :proxy_factories
27
+
28
+ def proxy_factory
29
+ proxy_factories
30
+ end
31
+
32
+ def add_proxy_factories hash
33
+ hash.each_pair do |name, factory|
34
+ factory = if factory.kind_of?(Class)
35
+ Party::Proxy::Factory.new(factory)
36
+ else
37
+ case factory
38
+ when Array
39
+ fac = factory.first
40
+ meth = factory.last if factory.size == 2
41
+ raise ArgumentError, "Factory must be a Class, was #{fac}" if !fac.kind_of?(Class)
42
+ raise ArgumentError, "Factory method be a label, was #{meth}" if meth && !meth.kind_of_label?
43
+ Party::Proxy::Factory.new(fac, meth)
44
+ else
45
+ raise ArgumentError, "Factory must be a Class or have a #create method: #{factory}" if !factory.respond_to?(:create)
46
+ factory
47
+ end
48
+ end
49
+ self.proxy_factories ||= {}
50
+ self.proxy_factories.merge!(name.to_sym => factory) if name.kind_of_label?
51
+ end
52
+ end
53
+ alias_method :add_proxy_factory, :add_proxy_factories
54
+
55
+ # Add instance proxy methods
56
+ def proxy_for obj, *methods
57
+ check = last_arg_value({:check => false}, methods)
58
+ rename_methods = last_arg_value({:rename => {}}, methods)
59
+ methods.delete(:rename) if rename_methods
60
+
61
+ methods.to_symbols.flat_uniq.each do |meth|
62
+ if check
63
+ raise ArgumentError, "No such object to proxy #{obj}" if !self.respond_to?(obj)
64
+ raise ArgumentError, "No such method to proxy for #{obj}" if !self.send(obj).respond_to?(meth)
65
+ end
66
+ class_eval %{
67
+ define_method :#{meth} do
68
+ #{obj}.send(:#{meth}) if #{obj}
69
+ end
70
+ }
71
+ end
72
+
73
+ rename_methods.each_pair do |meth, new_meth|
74
+ if check
75
+ raise ArgumentError, "No such object to proxy #{obj}" if !self.respond_to?(obj)
76
+ raise ArgumentError, "No such method to proxy for #{obj}" if !self.send(obj).respond_to?(meth)
77
+ end
78
+ class_eval %{
79
+ define_method :#{new_meth} do
80
+ #{obj}.send(:#{meth}) if #{obj}
81
+ end
82
+ }
83
+ end
84
+ end
85
+
86
+ # Add instance proxy methods
87
+ def proxy_accessors_for obj, *methods
88
+ proxy_for obj, methods
89
+ check = last_arg_value({:check => false}, methods)
90
+ rename_methods = last_arg_value({:rename => {}}, methods)
91
+ methods.delete(:rename) if rename_methods
92
+
93
+ methods.to_symbols.flat_uniq.each do |meth|
94
+ if check
95
+ raise ArgumentError, "No such object to proxy #{obj}" if !self.respond_to?(obj)
96
+ raise ArgumentError, "No such method #{meth} to proxy for #{obj}" if !self.send(obj).respond_to?(:"#{meth}=")
97
+ end
98
+ class_eval %{
99
+ define_method :#{meth}= do |arg|
100
+ self.#{obj} ||= create_in_factory(:#{obj})
101
+ self.#{obj} ||= self.class.send(:create_in_factory, :#{obj})
102
+ #{obj}.send(:#{meth}=, arg) if #{obj}
103
+ end
104
+ }
105
+ end
106
+
107
+ rename_methods.each_pair do |meth, new_meth|
108
+ if check
109
+ raise ArgumentError, "No such object to proxy #{obj}" if !self.respond_to?(obj)
110
+ raise ArgumentError, "No such method #{meth} to proxy for #{obj}" if !self.send(obj).respond_to?(:"#{meth}=")
111
+ end
112
+ class_eval %{
113
+ define_method :#{new_meth}= do |arg|
114
+ self.#{obj} ||= create_in_factory(:#{obj})
115
+ self.#{obj} ||= self.class.send(:create_in_factory, :#{obj})
116
+ #{obj}.send(:#{meth}=, arg) if #{obj}
117
+ end
118
+ }
119
+ end
120
+ end
121
+
122
+ # Add proxy methods only to the instance object
123
+ def instance_proxy_for obj, *methods
124
+ check = last_arg_value({:check => false}, methods)
125
+ rename_methods = last_arg_value({:rename => {}}, methods)
126
+ methods.delete(:rename) if rename_methods
127
+
128
+ methods.to_symbols.flat_uniq.each do |meth|
129
+ if check
130
+ raise ArgumentError, "No such object to proxy #{obj}" if !self.respond_to?(obj)
131
+ raise ArgumentError, "No such method to proxy for #{obj}" if !self.send(obj).respond_to?(meth)
132
+ end
133
+ instance_eval %{
134
+ class << self
135
+ define_method :#{meth} do
136
+ #{obj}.send(:#{meth}) if #{obj}
137
+ end
138
+ end
139
+ }
140
+ end
141
+
142
+ rename_methods.each_pair do |meth, new_meth|
143
+ if check
144
+ raise ArgumentError, "No such object to proxy #{obj}" if !self.respond_to?(obj)
145
+ raise ArgumentError, "No such method to proxy for #{obj}" if !self.send(obj).respond_to?(meth)
146
+ end
147
+ instance_eval %{
148
+ class << self
149
+ define_method :#{new_meth} do
150
+ #{obj}.send(:#{meth}) if #{obj}
151
+ end
152
+ end
153
+ }
154
+ end
155
+ end
156
+
157
+ # Add proxy methods only to the instance object
158
+ def instance_proxy_accessors_for obj, *methods
159
+ instance_proxy_for obj, methods
160
+ check = last_arg_value({:check => false}, methods)
161
+
162
+ rename_methods = last_arg_value({:rename => {}}, methods)
163
+ methods.delete(:rename) if rename_methods
164
+
165
+ methods.to_symbols.flat_uniq.each do |meth|
166
+ if check
167
+ raise ArgumentError, "No such object to proxy #{obj}" if !self.respond_to?(obj)
168
+ raise ArgumentError, "No such method #{meth} to proxy for #{obj}" if !self.send(obj).respond_to?(:"#{meth}=")
169
+ end
170
+ instance_eval %{
171
+ class << self
172
+ define_method :#{meth}= do |arg|
173
+ self.#{obj} ||= create_in_factory(:#{obj})
174
+ self.#{obj} ||= self.class.send(:create_in_factory, :#{obj})
175
+ #{obj}.send(:#{meth}=, arg) if #{obj}
176
+ end
177
+ end
178
+ }
179
+ end
180
+
181
+ rename_methods.each_pair do |meth, new_meth|
182
+ if check
183
+ raise ArgumentError, "No such object to proxy #{obj}" if !self.respond_to?(obj)
184
+ raise ArgumentError, "No such method to proxy for #{obj}" if !self.send(obj).respond_to?(meth)
185
+ end
186
+ instance_eval %{
187
+ class << self
188
+ define_method :#{new_meth}= do |arg|
189
+ self.#{obj} ||= create_in_factory(:#{obj})
190
+ self.#{obj} ||= self.class.send(:create_in_factory, :#{obj})
191
+ #{obj}.send(:#{meth}=, arg) if #{obj}
192
+ end
193
+ end
194
+ }
195
+ end
196
+ end
197
+
198
+ def named_proxies hash
199
+ raise ArgumentError, "Argument must be a hash" if !hash.kind_of? Hash
200
+ self.class.send :include, Party::Proxy
201
+ hash.each_pair do |proxy, methods|
202
+ instance_proxy_accessors_for proxy, methods
203
+ end
204
+ end
205
+
206
+ protected
207
+
208
+ def create_in_factory name
209
+ raise ArgumentError, "Factory name must be a label, was #{name}" if !name.kind_of_label?
210
+ proxy_factory[name].create if !send(name) && proxy_factory && proxy_factory[name]
211
+ end
6
212
  end
7
213
 
8
214
  # Define class methods here.
9
- module ClassMethods
10
- attr_accessor :proxies
215
+ module ClassMethods
216
+ attr_accessor :proxies
217
+ attr_accessor :proxy_factories
218
+
219
+ def proxy_factory
220
+ proxy_factories
221
+ end
222
+
223
+ def remove_proxy_factory name
224
+ @proxy_factories[name] = nil
225
+ end
226
+
227
+ def remove_proxy_factories
228
+ self.proxy_factories = nil
229
+ end
230
+
231
+ def add_proxy_factories hash
232
+ hash.each_pair do |name, factory|
233
+ factory = if factory.kind_of?(Class)
234
+ Party::Proxy::Factory.new(factory)
235
+ else
236
+ case factory
237
+ when Array
238
+ fac = factory.first
239
+ meth = factory.last if factory.size == 2
240
+ raise ArgumentError, "Factory must be a Class, was #{fac}" if !fac.kind_of?(Class)
241
+ raise ArgumentError, "Factory method be a label, was #{meth}" if meth && !meth.kind_of_label?
242
+ Party::Proxy::Factory.new(fac, meth)
243
+ else
244
+ raise ArgumentError, "Factory must be a Class or have a #create method: #{factory}" if !factory.respond_to?(:create)
245
+ factory
246
+ end
247
+ end
248
+ self.proxy_factories ||= {}
249
+ self.proxy_factories.merge!(name.to_sym => factory) if name.kind_of_label?
250
+ end
251
+ end
252
+ alias_method :add_proxy_factory, :add_proxy_factories
253
+
254
+
255
+ def remove_proxy name
256
+ proxies.delete(name)
257
+ end
258
+
259
+ def proxy_for obj, *methods
260
+ rename_methods = last_arg_value({:rename => {}}, methods)
261
+ methods.delete(:rename) if rename_methods
262
+
263
+ methods.flat_uniq.each do |meth|
264
+ name = meth.to_sym
265
+ define_method name do
266
+ send(obj).send(name) if send(obj)
267
+ end
268
+ end
269
+
270
+ rename_methods.each_pair do |meth, new_meth|
271
+ name = meth.to_sym
272
+ define_method new_meth.to_sym do
273
+ send(obj).send(name) if send(obj)
274
+ end
275
+ end
276
+ end
277
+
278
+ def proxy_accessors_for obj, *methods
279
+ proxy_for obj, methods
280
+
281
+ rename_methods = last_arg_value({:rename => {}}, methods)
282
+ methods.delete(:rename) if rename_methods
283
+
284
+ methods.flat_uniq.each do |meth|
285
+ name = meth.to_sym
286
+ obj_name = obj.to_sym
287
+ define_method name do |arg|
288
+ send(obj_name).send('||=', create_in_factory(obj_name))
289
+ send(obj_name).send("#{name}=", arg) if send(obj)
290
+ end
291
+ end
292
+
293
+ rename_methods.each_pair do |meth, new_meth|
294
+ name = meth.to_sym
295
+ obj_name = obj.to_sym
296
+ define_method new_meth.to_sym do |arg|
297
+ send(obj_name).send('||=', create_in_factory(obj_name))
298
+ send(obj_name).send("#{name}=", arg) if send(obj)
299
+ end
300
+ end
301
+ end
302
+
303
+ protected
304
+
305
+ def create_in_factory name
306
+ proxy_factory[name].create if proxy_factory && proxy_factory[name]
307
+ end
11
308
  end
12
309
 
13
310
  # proxy to state
14
311
  def method_missing(name, *args, &block)
312
+ return if !self.class.proxies
15
313
  self.class.proxies.each do |proxi|
16
314
  proxy_obj = self.send proxi
17
- return proxy_obj.send name, *args, &block if proxy_obj.respond_to? :"#{name}"
315
+ return proxy_obj.send(name, *args, &block) if proxy_obj.respond_to? :"#{name}"
18
316
  end
19
317
  super
20
318
  end
21
319
  end
22
320
  end
23
321
 
24
- class Class
322
+ class Module
323
+ def party_proxy
324
+ include Party::Proxy
325
+ end
326
+ alias_method :proxy_party, :party_proxy
327
+
328
+ def named_proxies hash
329
+ raise ArgumentError, "Argument must be a hash" if !hash.kind_of? Hash
330
+ include Party::Proxy
331
+ hash.each_pair do |proxy, methods|
332
+ proxy_accessors_for proxy, methods
333
+ end
334
+ end
335
+
25
336
  def proxy *proxy_objs
26
337
  include Party::Proxy
27
338
 
28
- proxy_objs.each do |proxy_obj|
339
+ proxy_objs.flat_uniq.each do |proxy_obj|
340
+ raise ArgumentError, "bad proxy object #{proxy_obj}" if !proxy_obj.kind_of_label?
29
341
  attr_accessor proxy_obj
30
342
  @proxies ||= []
31
- @proxies << proxy_obj
343
+ @proxies << proxy_obj if !@proxies.include? proxy_obj
32
344
  end
33
345
  end
34
346
  end
@@ -0,0 +1,57 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{proxy_party}
8
+ s.version = "0.2.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Kristian Mandrup"]
12
+ s.date = %q{2011-02-21}
13
+ s.description = %q{Method missing proxy pattern}
14
+ s.email = %q{kmandrup@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.textile"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "LICENSE",
23
+ "README.textile",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/proxy_party.rb",
27
+ "proxy_party.gemspec",
28
+ "spec/proxy_party_complex_spec.rb",
29
+ "spec/proxy_party_spec.rb",
30
+ "spec/spec_helper.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/kristianmandrup/proxy_party}
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.5.2}
35
+ s.summary = %q{Add proxy functionality the fun way}
36
+ s.test_files = [
37
+ "spec/proxy_party_complex_spec.rb",
38
+ "spec/proxy_party_spec.rb",
39
+ "spec/spec_helper.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ s.specification_version = 3
44
+
45
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_runtime_dependency(%q<sugar-high>, [">= 0.3.5"])
47
+ s.add_development_dependency(%q<rspec>, [">= 2.4.0"])
48
+ else
49
+ s.add_dependency(%q<sugar-high>, [">= 0.3.5"])
50
+ s.add_dependency(%q<rspec>, [">= 2.4.0"])
51
+ end
52
+ else
53
+ s.add_dependency(%q<sugar-high>, [">= 0.3.5"])
54
+ s.add_dependency(%q<rspec>, [">= 2.4.0"])
55
+ end
56
+ end
57
+
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ class Module
4
+ include Party::Proxy
5
+ end
6
+
7
+ class Address
8
+ attr_accessor :street
9
+ end
10
+
11
+ module Proxies
12
+ proxy_accessors_for :address, :street
13
+ end
14
+
15
+ class Place
16
+ attr_accessor :address
17
+ # include Proxies
18
+
19
+ def self.inherited(base)
20
+ # Alternative
21
+ # base.class_eval do
22
+ # send :include, Proxies
23
+ # end
24
+ base.send :include, Proxies
25
+ # puts base.methods.sort
26
+ end
27
+ end
28
+
29
+ class OtherPlace
30
+ attr_accessor :address
31
+
32
+ proxy_accessors_for :address, :street
33
+ end
34
+
35
+ class Pickup
36
+ attr_accessor :address
37
+
38
+ include Proxies
39
+ end
40
+
41
+ class Dropoff < Place
42
+ end
43
+
44
+ describe Party::Proxy do
45
+ context 'Dropoff inherits from Place' do
46
+ before do
47
+ @dropoff = Dropoff.new
48
+ @pickup = Pickup.new
49
+ @other = OtherPlace.new
50
+ end
51
+
52
+ it 'should add proxies for address' do
53
+ @dropoff.should respond_to :street
54
+ @pickup.should respond_to :street
55
+ @other.should respond_to :street
56
+
57
+ @dropoff.should respond_to :street=
58
+ @pickup.should respond_to :street=
59
+ @other.should respond_to :street=
60
+ end
61
+ end
62
+ end
@@ -1,37 +1,149 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  class State
4
4
  attr_accessor :name
5
-
6
- def initialize(name)
7
- @name = name
8
- end
9
- end
5
+
6
+ def initialize name = nil
7
+ @name = name
8
+ end
9
+ end
10
10
 
11
11
  class Info
12
12
  attr_accessor :text
13
-
14
- def initialize(text)
15
- @text = text
16
- end
17
- end
18
13
 
14
+ def initialize text = nil
15
+ @text = text
16
+ end
17
+ end
19
18
 
20
- module Party
19
+ class Mic
20
+ attr_accessor :speak, :yawn
21
+
22
+ def initialize text = nil
23
+ @speak = text
24
+ end
25
+
26
+ def speak_it!
27
+ speak
28
+ end
29
+
30
+ def self.create_empty
31
+ mic = self.new
32
+ mic.speak = 'empty'
33
+ mic.yawn = 'miau'
34
+ mic
35
+ end
36
+ end
37
+
38
+ module Party
21
39
  class Subject
40
+ attr_accessor :mic
41
+
22
42
  proxy :state, :info
23
-
24
- def initialize(name)
43
+
44
+ def initialize name = nil
25
45
  @state = State.new name
26
- @info = Info.new 'hello'
46
+ @info = Info.new 'hello'
27
47
  end
28
48
  end
29
49
  end
30
50
 
51
+ module PartyModule
52
+ party_proxy
53
+ end
54
+
55
+ class PartyClass
56
+ proxy_party
57
+ end
58
+
59
+
60
+
31
61
  describe Party::Proxy do
32
- it "proxies state so it can call name directly on subject" do
33
- subject = Party::Subject.new 'kristian'
34
- subject.name.should == 'kristian'
35
- subject.text.should == 'hello'
62
+ describe '#party_proxy' do
63
+ it "Should add party proxy to Module" do
64
+ PartyModule.methods.grep(/proxy_for/).should_not be_empty
65
+ PartyModule.should respond_to(:add_proxy_factory)
66
+ end
67
+
68
+ it "Should add party proxy to Class" do
69
+ PartyClass.methods.grep(/proxy_for/).should_not be_empty
70
+ PartyClass.should respond_to(:add_proxy_factory)
71
+ end
72
+ end
73
+
74
+ describe '#proxy' do
75
+ it "proxies state and info so it can call name directly on subject" do
76
+ subject = Party::Subject.new 'kristian'
77
+ subject.name.should == 'kristian'
78
+ end
79
+ end
80
+
81
+ describe '#proxy_for' do
82
+ it "proxies speak_it! on mic" do
83
+ subject = Party::Subject.new 'kristian'
84
+ subject.mic = Mic.new 'hello'
85
+ subject.instance_proxy_for :mic, :speak_it!
86
+ subject.speak_it!.should == 'hello'
87
+ end
88
+
89
+ it "handles proxy when the proxied object (mic) is nil" do
90
+ subject = Party::Subject.new 'kristian'
91
+ subject.instance_proxy_for :mic, :speak_it!
92
+ subject.speak_it!.should == nil
93
+ end
94
+
95
+ it "handles proxy when the proxied object (mic) is set to nil later" do
96
+ subject = Party::Subject.new 'kristian'
97
+ subject.mic = Mic.new 'hello'
98
+ subject.instance_proxy_for :mic, :speak_it!, :check => true
99
+ subject.mic = nil
100
+ subject.speak_it!.should == nil
101
+ end
102
+
103
+ it "errors when proxy when the proxied object (mic) is nil and nil check is on" do
104
+ subject = Party::Subject.new 'kristian'
105
+ subject.mic = nil
106
+ lambda {subject.proxy_for :mic, :speak_it!, :check => true}.should raise_error
107
+ end
108
+
109
+ it "proxies uses class level proxy factory with factory method" do
110
+ subject = Party::Subject.new 'kristian'
111
+ subject.add_proxy_factory :mic => [Mic, :create_empty]
112
+ subject.instance_proxy_accessors_for :mic, :speak, :yawn
113
+ subject.speak = 'blip'
114
+ subject.speak.should == 'blip'
115
+ subject.yawn.should == 'miau'
116
+ end
117
+ end
118
+
119
+ describe '#proxy_for renaming using :as' do
120
+ it "proxies speak_it! on mic" do
121
+ subject = Party::Subject.new 'kristian'
122
+ subject.mic = Mic.new 'hello'
123
+ subject.instance_proxy_for :mic, :rename => {:speak_it! => :speak_up!}
124
+ subject.speak_up!.should == 'hello'
125
+ end
126
+
127
+ it "proxies uses class level proxy factory with factory method" do
128
+ subject = Party::Subject.new 'kristian'
129
+ subject.add_proxy_factory :mic => [Mic, :create_empty]
130
+ subject.instance_proxy_accessors_for :mic, :rename => {:speak => :yell, :yawn => :gaab}
131
+ subject.yell = 'blip'
132
+ subject.yell.should == 'blip'
133
+ subject.gaab.should == 'miau'
134
+ end
135
+ end
136
+
137
+ describe '#named_proxies' do
138
+ it "proxies select :mic and :state methods" do
139
+ subject = Party::Subject.new 'kristian'
140
+ subject.mic = Mic.new 'hello'
141
+ subject.named_proxies :mic => :speak, :state => :name
142
+ subject.speak = 'do it!'
143
+ subject.speak.should == 'do it!'
144
+
145
+ subject.name = 'kris'
146
+ subject.name.should == 'kris'
147
+ end
36
148
  end
37
149
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  require 'rspec'
2
- require 'rspec/autorun'
2
+ # require 'rspec/autorun'
3
3
  require 'proxy_party'
metadata CHANGED
@@ -1,75 +1,84 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: proxy_party
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 1
8
- - 0
9
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Kristian Mandrup
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2010-06-18 00:00:00 +02:00
12
+ date: 2011-02-21 00:00:00.000000000 +01:00
18
13
  default_executable:
19
- dependencies: []
20
-
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: sugar-high
17
+ requirement: &2157117440 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.3.5
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2157117440
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ requirement: &2157116940 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 2.4.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *2157116940
21
37
  description: Method missing proxy pattern
22
38
  email: kmandrup@gmail.com
23
39
  executables: []
24
-
25
40
  extensions: []
26
-
27
- extra_rdoc_files:
41
+ extra_rdoc_files:
28
42
  - LICENSE
29
- - README.markdown
30
- files:
43
+ - README.textile
44
+ files:
31
45
  - .document
32
- - .gitignore
46
+ - .rspec
33
47
  - LICENSE
34
- - README.markdown
48
+ - README.textile
35
49
  - Rakefile
36
50
  - VERSION
37
51
  - lib/proxy_party.rb
52
+ - proxy_party.gemspec
53
+ - spec/proxy_party_complex_spec.rb
38
54
  - spec/proxy_party_spec.rb
39
- - spec/spec.opts
40
55
  - spec/spec_helper.rb
41
56
  has_rdoc: true
42
57
  homepage: http://github.com/kristianmandrup/proxy_party
43
58
  licenses: []
44
-
45
59
  post_install_message:
46
- rdoc_options:
47
- - --charset=UTF-8
48
- require_paths:
60
+ rdoc_options: []
61
+ require_paths:
49
62
  - lib
50
- required_ruby_version: !ruby/object:Gem::Requirement
63
+ required_ruby_version: !ruby/object:Gem::Requirement
51
64
  none: false
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- segments:
56
- - 0
57
- version: "0"
58
- required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
70
  none: false
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- segments:
64
- - 0
65
- version: "0"
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
66
75
  requirements: []
67
-
68
76
  rubyforge_project:
69
- rubygems_version: 1.3.7
77
+ rubygems_version: 1.5.2
70
78
  signing_key:
71
79
  specification_version: 3
72
80
  summary: Add proxy functionality the fun way
73
- test_files:
81
+ test_files:
82
+ - spec/proxy_party_complex_spec.rb
74
83
  - spec/proxy_party_spec.rb
75
84
  - spec/spec_helper.rb
data/.gitignore DELETED
@@ -1,21 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC
data/README.markdown DELETED
@@ -1,67 +0,0 @@
1
- # Proxy Party
2
-
3
- Greatly facilitates adding proxies through the proxy method_missing pattern
4
-
5
- ## Install ##
6
-
7
- <code>$ gem install party_proxy</code>
8
-
9
- ## Usage Configuration ##
10
-
11
- <code>require 'party_proxy'</code>
12
-
13
- ## Usage ##
14
-
15
- <pre><code>
16
- class State
17
- attr_accessor :name
18
-
19
- def initialize(name)
20
- @name = name
21
- end
22
- end
23
-
24
- class Info
25
- attr_accessor :text
26
-
27
- def initialize(text)
28
- @text = text
29
- end
30
- end
31
-
32
- module Party
33
- class Subject
34
- # proxy state and info objects to make their methods
35
- # directly accessible from subject objects
36
- proxy :state, :info
37
-
38
- def initialize(name)
39
- @state = State.new name
40
- @info = Info.new 'hello'
41
- end
42
- end
43
- end
44
-
45
- subject = Party::Subject.new 'kristian'
46
- # access 'name' directly through 'state' proxy
47
- puts subject.name
48
- # access 'text' directly through 'info' proxy
49
- puts subject.text
50
-
51
- => 'kristian'
52
- => 'hello'
53
- </code></pre>
54
-
55
- ## Note on Patches/Pull Requests ##
56
-
57
- * Fork the project.
58
- * Make your feature addition or bug fix.
59
- * Add tests for it. This is important so I don't break it in a
60
- future version unintentionally.
61
- * Commit, do not mess with rakefile, version, or history.
62
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
63
- * Send me a pull request. Bonus points for topic branches.
64
-
65
- ## Copyright ##
66
-
67
- Copyright (c) 2010 Kristian Mandrup. See LICENSE for details.