proxy_party 0.1.0 → 0.2.1

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.
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.