proxeze 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +13 -0
- data/Gemfile.lock +45 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +113 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/lib/proxeze.rb +52 -0
- data/proxeze.gemspec +80 -0
- data/spec/definitions.rb +74 -0
- data/spec/proxeze_spec.rb +151 -0
- data/spec/spec_helper.rb +15 -0
- metadata +206 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
archive-tar-minitar (0.5.2)
|
5
|
+
columnize (0.3.2)
|
6
|
+
diff-lcs (1.1.2)
|
7
|
+
git (1.2.5)
|
8
|
+
jeweler (1.5.2)
|
9
|
+
bundler (~> 1.0.0)
|
10
|
+
git (>= 1.2.5)
|
11
|
+
rake
|
12
|
+
linecache19 (0.5.11)
|
13
|
+
ruby_core_source (>= 0.1.4)
|
14
|
+
rake (0.8.7)
|
15
|
+
rcov (0.9.9)
|
16
|
+
rcov (0.9.9-java)
|
17
|
+
rspec (2.4.0)
|
18
|
+
rspec-core (~> 2.4.0)
|
19
|
+
rspec-expectations (~> 2.4.0)
|
20
|
+
rspec-mocks (~> 2.4.0)
|
21
|
+
rspec-core (2.4.0)
|
22
|
+
rspec-expectations (2.4.0)
|
23
|
+
diff-lcs (~> 1.1.2)
|
24
|
+
rspec-mocks (2.4.0)
|
25
|
+
ruby-debug-base19 (0.11.24)
|
26
|
+
columnize (>= 0.3.1)
|
27
|
+
linecache19 (>= 0.5.11)
|
28
|
+
ruby_core_source (>= 0.1.4)
|
29
|
+
ruby-debug19 (0.11.6)
|
30
|
+
columnize (>= 0.3.1)
|
31
|
+
linecache19 (>= 0.5.11)
|
32
|
+
ruby-debug-base19 (>= 0.11.19)
|
33
|
+
ruby_core_source (0.1.4)
|
34
|
+
archive-tar-minitar (>= 0.5.2)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
java
|
38
|
+
ruby
|
39
|
+
|
40
|
+
DEPENDENCIES
|
41
|
+
bundler (~> 1.0.0)
|
42
|
+
jeweler (~> 1.5.2)
|
43
|
+
rcov
|
44
|
+
rspec (~> 2.4.0)
|
45
|
+
ruby-debug19
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Jason Rogers
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
= proxeze
|
2
|
+
|
3
|
+
A basic proxy/delegate framework for Ruby that will allow you to wrap any object with a proxy instance. For more information about the Proxy and Delegate patterns, check out http://en.wikipedia.org/wiki/Proxy_pattern and http://en.wikipedia.org/wiki/Delegation_pattern respectively.
|
4
|
+
|
5
|
+
== Details
|
6
|
+
|
7
|
+
When Proxeze proxies an object, it creates a delegate class under its namespace (using Ruby's built-in Delegate class) that mirrors your class. It overrides your class' #new method so that when you create instances of your class, you get back the proxy object instead. In this way, you don't have to change the way you instantiate your objects, but you get the benefit of the proxy pattern.
|
8
|
+
|
9
|
+
== How does that help me?
|
10
|
+
|
11
|
+
Examples tell it best... In this example we have a tree structure of Categories. At some point during the execution of our program we want to hide certain categories in that tree, without adding extra behavior to Category, and without changing the state of the Category instances themselves. Enter the Proxy.
|
12
|
+
|
13
|
+
class Category
|
14
|
+
attr_accessor :categories
|
15
|
+
attr_reader :name
|
16
|
+
|
17
|
+
def initialize name
|
18
|
+
@name = name
|
19
|
+
@categories = []
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# now every time we instantiate Category, we will get back a Proxeze::Category instance
|
24
|
+
Proxeze.proxy Category
|
25
|
+
|
26
|
+
c1, c2, c3 = Category.new('1'), Category.new('2'), Category.new('3')
|
27
|
+
c1.categories = [c2, c3]
|
28
|
+
c2.categories << Category.new('4')
|
29
|
+
c2.categories << Category.new('5')
|
30
|
+
c6 = Category.new('6')
|
31
|
+
c2.categories << c6
|
32
|
+
c6.categories << Category.new('7')
|
33
|
+
c6.categories << Category.new('8')
|
34
|
+
|
35
|
+
# now we have a tree like this:
|
36
|
+
# c1
|
37
|
+
# ____||____
|
38
|
+
# || ||
|
39
|
+
# c2 c3
|
40
|
+
# ____||____
|
41
|
+
# || || ||
|
42
|
+
# c4 c5 c6
|
43
|
+
# ___||___
|
44
|
+
# || ||
|
45
|
+
# c7 c8
|
46
|
+
|
47
|
+
Let's say we need to be able to hide c6 and its children at some point, to do that we can run the following code:
|
48
|
+
|
49
|
+
module Visibility
|
50
|
+
def visible?
|
51
|
+
@visible = true if @visible.nil?
|
52
|
+
@visible
|
53
|
+
end
|
54
|
+
|
55
|
+
def be_invisible!
|
56
|
+
@visible = false
|
57
|
+
categories.each {|e| e.be_invisible!}
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def be_visible!
|
62
|
+
@visible = true
|
63
|
+
categories.each {|e| e.be_visible!}
|
64
|
+
self
|
65
|
+
end
|
66
|
+
end
|
67
|
+
Proxeze::Category.send :include, Visibility
|
68
|
+
|
69
|
+
c6.be_invisible!
|
70
|
+
|
71
|
+
So, we've added behavior to the proxied objects, but not the Category objects themselves.
|
72
|
+
|
73
|
+
You can also proxy an object without overriding the #new method on its class:
|
74
|
+
|
75
|
+
p = Proxeze.for(1)
|
76
|
+
p.class # Proxeze::Fixnum
|
77
|
+
p.__getobj__.class # Fixnum
|
78
|
+
|
79
|
+
class A
|
80
|
+
attr_accessor :foo
|
81
|
+
def initialize; @foo = 1; end
|
82
|
+
end
|
83
|
+
|
84
|
+
p = Proxeze.for(A.new)
|
85
|
+
p.class # => Proxeze::A
|
86
|
+
p.__getobj__.class # => A
|
87
|
+
|
88
|
+
This allows you to proxy specific instances of your classes without proxying all subsequent instances. Of course, you can proxy the class and all subsequent instances even after you've proxied a specific instance:
|
89
|
+
|
90
|
+
p = Proxeze.for(A.new)
|
91
|
+
p.class # => Proxeze::A
|
92
|
+
p.__getobj__.class # => A
|
93
|
+
|
94
|
+
Proxeze.proxeze A
|
95
|
+
a = A.new
|
96
|
+
a.class # => Proxeze::A
|
97
|
+
a.__getobj__.class # => A
|
98
|
+
|
99
|
+
== Contributing to proxeze
|
100
|
+
|
101
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
102
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
103
|
+
* Fork the project
|
104
|
+
* Start a feature/bugfix branch
|
105
|
+
* Commit and push until you are happy with your contribution
|
106
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
107
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
108
|
+
|
109
|
+
== Copyright
|
110
|
+
|
111
|
+
Copyright (c) 2011 Jason Rogers. See LICENSE.txt for
|
112
|
+
further details.
|
113
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "proxeze"
|
16
|
+
gem.homepage = "http://github.com/jacaetevha/proxeze"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{A basic proxy/delegate framework for Ruby that will allow you to wrap any object with a proxy instance.}
|
19
|
+
gem.description = %Q{A basic proxy/delegate framework for Ruby that will allow you to wrap any object with a proxy instance. For more information about the Proxy and Delegate patterns, check out http://en.wikipedia.org/wiki/Proxy_pattern and http://en.wikipedia.org/wiki/Delegation_pattern respectively.}
|
20
|
+
gem.email = "jacaetevha@gmail.com"
|
21
|
+
gem.authors = ["Jason Rogers"]
|
22
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
25
|
+
gem.add_development_dependency 'rspec', '~> 2.4.0'
|
26
|
+
gem.add_development_dependency "bundler", "~> 1.0.0"
|
27
|
+
gem.add_development_dependency "jeweler", "~> 1.5.2"
|
28
|
+
gem.add_development_dependency "rcov", ">= 0"
|
29
|
+
end
|
30
|
+
Jeweler::RubygemsDotOrgTasks.new
|
31
|
+
|
32
|
+
require 'rspec/core'
|
33
|
+
require 'rspec/core/rake_task'
|
34
|
+
RSpec::Core::RakeTask.new(:specs) do |spec|
|
35
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
36
|
+
spec.rspec_opts = '-c --format documentation'
|
37
|
+
end
|
38
|
+
|
39
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
40
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
41
|
+
spec.rcov = true
|
42
|
+
spec.rspec_opts = '-c --format documentation'
|
43
|
+
end
|
44
|
+
|
45
|
+
task :default => :specs
|
46
|
+
|
47
|
+
require 'rake/rdoctask'
|
48
|
+
Rake::RDocTask.new do |rdoc|
|
49
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "proxeze #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/proxeze.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Proxeze
|
4
|
+
if RUBY_VERSION =~ /1\.9/
|
5
|
+
def self.class_defined? name
|
6
|
+
const_defined? name, false
|
7
|
+
end
|
8
|
+
else
|
9
|
+
def self.class_defined? name
|
10
|
+
const_defined? name
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.proxy target_class, redefine_new_method = true
|
15
|
+
cls_name = target_class.name.gsub '::', ''
|
16
|
+
unless self.class_defined? cls_name
|
17
|
+
cls = DelegateClass target_class
|
18
|
+
cls.send :include, self
|
19
|
+
self.const_set cls_name, cls
|
20
|
+
end
|
21
|
+
|
22
|
+
# we have to collect the methods as Strings here because
|
23
|
+
# 1.9 changed the implementation to return Symbols instead of Strings
|
24
|
+
if redefine_new_method && !target_class.methods.collect{|e| e.to_s}.include?('new_with_extra_behavior')
|
25
|
+
meta = class << target_class; self; end
|
26
|
+
meta.class_eval %Q{
|
27
|
+
def new_with_extra_behavior *args, &blk
|
28
|
+
#{cls_name}.new( self.new_without_extra_behavior(*args, &blk) )
|
29
|
+
end
|
30
|
+
alias_method :new_without_extra_behavior, :new
|
31
|
+
alias_method :new, :new_with_extra_behavior
|
32
|
+
}, __FILE__, __LINE__
|
33
|
+
end
|
34
|
+
|
35
|
+
self.const_get cls_name
|
36
|
+
end
|
37
|
+
|
38
|
+
# create a proxy object for the given object
|
39
|
+
def self.for object
|
40
|
+
self.proxy( object.class, false ).new( object )
|
41
|
+
end
|
42
|
+
|
43
|
+
# create a new proxy around a clone of my delegate object
|
44
|
+
def clone
|
45
|
+
Proxeze.for __getobj__.clone
|
46
|
+
end
|
47
|
+
|
48
|
+
# create a new proxy object for my delegate
|
49
|
+
def new_proxy
|
50
|
+
Proxeze.for __getobj__
|
51
|
+
end
|
52
|
+
end
|
data/proxeze.gemspec
ADDED
@@ -0,0 +1,80 @@
|
|
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{proxeze}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Jason Rogers"]
|
12
|
+
s.date = %q{2011-02-02}
|
13
|
+
s.description = %q{A basic proxy/delegate framework for Ruby that will allow you to wrap any object with a proxy instance. For more information about the Proxy and Delegate patterns, check out http://en.wikipedia.org/wiki/Proxy_pattern and http://en.wikipedia.org/wiki/Delegation_pattern respectively.}
|
14
|
+
s.email = %q{jacaetevha@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"Gemfile",
|
21
|
+
"Gemfile.lock",
|
22
|
+
"LICENSE.txt",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/proxeze.rb",
|
27
|
+
"proxeze.gemspec",
|
28
|
+
"spec/definitions.rb",
|
29
|
+
"spec/proxeze_spec.rb",
|
30
|
+
"spec/spec_helper.rb"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/jacaetevha/proxeze}
|
33
|
+
s.licenses = ["MIT"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = %q{1.3.7}
|
36
|
+
s.summary = %q{A basic proxy/delegate framework for Ruby that will allow you to wrap any object with a proxy instance.}
|
37
|
+
s.test_files = [
|
38
|
+
"spec/definitions.rb",
|
39
|
+
"spec/proxeze_spec.rb",
|
40
|
+
"spec/spec_helper.rb"
|
41
|
+
]
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
45
|
+
s.specification_version = 3
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
48
|
+
s.add_development_dependency(%q<ruby-debug19>, [">= 0"])
|
49
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.4.0"])
|
50
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
51
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
52
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
53
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.4.0"])
|
54
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
55
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
56
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<ruby-debug19>, [">= 0"])
|
59
|
+
s.add_dependency(%q<rspec>, ["~> 2.4.0"])
|
60
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
61
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
62
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
63
|
+
s.add_dependency(%q<rspec>, ["~> 2.4.0"])
|
64
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
65
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
66
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
67
|
+
end
|
68
|
+
else
|
69
|
+
s.add_dependency(%q<ruby-debug19>, [">= 0"])
|
70
|
+
s.add_dependency(%q<rspec>, ["~> 2.4.0"])
|
71
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
72
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
73
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
74
|
+
s.add_dependency(%q<rspec>, ["~> 2.4.0"])
|
75
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
76
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
77
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
data/spec/definitions.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
module Testing
|
2
|
+
class NestedClass
|
3
|
+
def foo; 1; end
|
4
|
+
def bar; 10_000_009; end
|
5
|
+
def ==(other); other.foo == self.foo && other.bar == self.bar; end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class NonNestedClass
|
10
|
+
def baz; 2; end
|
11
|
+
def ==(other); other.baz == self.baz; end
|
12
|
+
end
|
13
|
+
|
14
|
+
module NewBaz
|
15
|
+
def self.included into
|
16
|
+
begin
|
17
|
+
into.instance_eval{ remove_method :baz }
|
18
|
+
rescue
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def baz; 'new baz'; end
|
23
|
+
end
|
24
|
+
|
25
|
+
module NewBar
|
26
|
+
def self.included into
|
27
|
+
begin
|
28
|
+
into.send :remove_method, :bar
|
29
|
+
rescue
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def bar; 'new bar'; end
|
34
|
+
end
|
35
|
+
|
36
|
+
class ClassForProxyingAnInstance
|
37
|
+
end
|
38
|
+
|
39
|
+
class ClassForProxyingAfterAnInstanceWasProxied
|
40
|
+
end
|
41
|
+
|
42
|
+
class Category
|
43
|
+
attr_accessor :categories
|
44
|
+
attr_reader :name
|
45
|
+
|
46
|
+
def initialize name
|
47
|
+
@name = name
|
48
|
+
@categories = []
|
49
|
+
end
|
50
|
+
|
51
|
+
def == other
|
52
|
+
other.name == self.name &&
|
53
|
+
other.categories == self.categories
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module Visibility
|
58
|
+
def visible?
|
59
|
+
@visible = true if @visible.nil?
|
60
|
+
@visible
|
61
|
+
end
|
62
|
+
|
63
|
+
def be_invisible!
|
64
|
+
@visible = false
|
65
|
+
categories.each {|e| e.be_invisible!}
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
def be_visible!
|
70
|
+
@visible = true
|
71
|
+
categories.each {|e| e.be_visible!}
|
72
|
+
self
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require 'definitions'
|
3
|
+
|
4
|
+
shared_examples_for "all wrapped classes" do
|
5
|
+
it "should wrap the class>>#new method so we get an instance of the proxy instead" do
|
6
|
+
Proxeze.proxy Testing::NestedClass
|
7
|
+
instance = Testing::NestedClass.new
|
8
|
+
instance.should respond_to(:__getobj__)
|
9
|
+
instance.should respond_to(:__setobj__)
|
10
|
+
instance.should be_kind_of(Proxeze::TestingNestedClass)
|
11
|
+
|
12
|
+
Proxeze.proxy NonNestedClass
|
13
|
+
instance = NonNestedClass.new
|
14
|
+
instance.should respond_to(:__getobj__)
|
15
|
+
instance.should respond_to(:__setobj__)
|
16
|
+
instance.should be_kind_of(Proxeze::NonNestedClass)
|
17
|
+
|
18
|
+
cls = Class.new
|
19
|
+
cls_name = Date.today.strftime('%B%d%H%m%s')
|
20
|
+
Object.const_set cls_name, cls
|
21
|
+
|
22
|
+
Proxeze.proxy cls
|
23
|
+
instance = cls.new
|
24
|
+
instance.should respond_to(:__getobj__)
|
25
|
+
instance.should respond_to(:__setobj__)
|
26
|
+
instance.should be_kind_of(Proxeze.const_get(cls_name))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe Proxeze do
|
31
|
+
it_should_behave_like "all wrapped classes"
|
32
|
+
|
33
|
+
it "should respond to the target object's methods" do
|
34
|
+
Proxeze.proxy Testing::NestedClass
|
35
|
+
instance = Testing::NestedClass.new
|
36
|
+
|
37
|
+
instance.should respond_to(:foo)
|
38
|
+
instance.foo.should == 1
|
39
|
+
|
40
|
+
instance.should respond_to(:bar)
|
41
|
+
instance.bar.should == 10_000_009
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should be able to add behavior to the proxy without disturbing the wrapped object" do
|
45
|
+
Proxeze.proxy Category
|
46
|
+
instance = Category.new('test')
|
47
|
+
|
48
|
+
instance.should_not respond_to(:visible?)
|
49
|
+
Proxeze::Category.send :include, Visibility
|
50
|
+
instance.should respond_to(:visible?)
|
51
|
+
instance.__getobj__.should_not respond_to(:visible?)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should operate on the proxy object seemlessly" do
|
55
|
+
Proxeze.proxy Category
|
56
|
+
Proxeze::Category.send :include, Visibility
|
57
|
+
|
58
|
+
c1, c2, c3 = Category.new('1'), Category.new('2'), Category.new('3')
|
59
|
+
c1.categories = [c2, c3]
|
60
|
+
c2.categories << Category.new('4')
|
61
|
+
c2.categories << Category.new('5')
|
62
|
+
c6 = Category.new('6')
|
63
|
+
c2.categories << c6
|
64
|
+
c6.categories << Category.new('7')
|
65
|
+
c6.categories << Category.new('8')
|
66
|
+
|
67
|
+
c1.should be_visible
|
68
|
+
c2.should be_visible
|
69
|
+
c2.categories.each do |cat|
|
70
|
+
cat.should be_visible
|
71
|
+
end
|
72
|
+
c3.should be_visible
|
73
|
+
c6.should be_visible
|
74
|
+
c6.categories.each do |cat|
|
75
|
+
cat.should be_visible
|
76
|
+
end
|
77
|
+
|
78
|
+
c6.be_invisible!
|
79
|
+
c6.should_not be_visible
|
80
|
+
c6.categories.each do |cat|
|
81
|
+
cat.should_not be_visible
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should proxy an object" do
|
86
|
+
Proxeze.class_defined?('ClassForProxyingAnInstance').should == false
|
87
|
+
instance = Proxeze.for(ClassForProxyingAnInstance.new)
|
88
|
+
ClassForProxyingAnInstance.methods.collect{|e| e.to_s}.include?('new_with_extra_behavior').should == false
|
89
|
+
ClassForProxyingAnInstance.methods.collect{|e| e.to_s}.include?('new_without_extra_behavior').should == false
|
90
|
+
Proxeze.class_defined?('ClassForProxyingAnInstance').should == true
|
91
|
+
|
92
|
+
instance.should_not respond_to(:visible?)
|
93
|
+
instance.class.send :include, Visibility
|
94
|
+
instance.should respond_to(:visible?)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should redefine the #new method when the class is proxied, even after an instance of the class was proxied" do
|
98
|
+
Proxeze.class_defined?('ClassForProxyingAfterAnInstanceWasProxied').should == false
|
99
|
+
instance = Proxeze.for(ClassForProxyingAfterAnInstanceWasProxied.new)
|
100
|
+
Proxeze.class_defined?('ClassForProxyingAfterAnInstanceWasProxied').should == true
|
101
|
+
|
102
|
+
Proxeze.proxy ClassForProxyingAfterAnInstanceWasProxied
|
103
|
+
instance = ClassForProxyingAfterAnInstanceWasProxied.new
|
104
|
+
instance.__getobj__.class.methods.collect{|e| e.to_s}.should include('new_without_extra_behavior')
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should create a new proxy around the same delegate object" do
|
108
|
+
Proxeze.proxy NonNestedClass
|
109
|
+
instance = NonNestedClass.new
|
110
|
+
copy = instance.new_proxy
|
111
|
+
|
112
|
+
instance.class.should == Proxeze::NonNestedClass
|
113
|
+
copy.class.should == Proxeze::NonNestedClass
|
114
|
+
|
115
|
+
instance.__getobj__.should be_equal(copy.__getobj__)
|
116
|
+
instance.__getobj__.should == copy.__getobj__
|
117
|
+
instance.baz.should == 2
|
118
|
+
copy.baz.should == 2
|
119
|
+
|
120
|
+
copy.class.send :include, NewBaz
|
121
|
+
instance.__getobj__.should == copy.__getobj__
|
122
|
+
instance.baz.should == 'new baz'
|
123
|
+
copy.baz.should == 'new baz'
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should create a new proxy around a clone of the delegate object" do
|
127
|
+
Proxeze.proxy Testing::NestedClass
|
128
|
+
instance = Testing::NestedClass.new
|
129
|
+
copy = instance.clone
|
130
|
+
|
131
|
+
instance.class.should == Proxeze::TestingNestedClass
|
132
|
+
copy.class.should == Proxeze::TestingNestedClass
|
133
|
+
|
134
|
+
instance.__getobj__.should_not be_equal(copy.__getobj__)
|
135
|
+
instance.__getobj__.should == copy.__getobj__
|
136
|
+
instance.bar.should == 10_000_009
|
137
|
+
copy.bar.should == 10_000_009
|
138
|
+
|
139
|
+
copy_meta = class << copy.__getobj__; self; end
|
140
|
+
copy_meta.send :include, NewBar
|
141
|
+
instance.bar.should == 10_000_009
|
142
|
+
copy.bar.should == 'new bar'
|
143
|
+
instance.__getobj__.should_not == copy.__getobj__
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should not attempt to redefine #new in the class of the proxied object" do
|
147
|
+
lambda{Proxeze.for(1)}.should_not raise_error(NameError)
|
148
|
+
proxy = Proxeze.for(1)
|
149
|
+
proxy.should be_kind_of(Proxeze::Fixnum)
|
150
|
+
end
|
151
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# $:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
# require 'proxeze'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
|
+
require 'rspec'
|
7
|
+
require 'proxeze'
|
8
|
+
|
9
|
+
# Requires supporting files with custom matchers and macros, etc,
|
10
|
+
# in ./support/ and its subdirectories.
|
11
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: proxeze
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Jason Rogers
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-02-02 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: ruby-debug19
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :development
|
31
|
+
prerelease: false
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rspec
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
segments:
|
41
|
+
- 2
|
42
|
+
- 4
|
43
|
+
- 0
|
44
|
+
version: 2.4.0
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: bundler
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 1
|
57
|
+
- 0
|
58
|
+
- 0
|
59
|
+
version: 1.0.0
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: jeweler
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ~>
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
segments:
|
71
|
+
- 1
|
72
|
+
- 5
|
73
|
+
- 2
|
74
|
+
version: 1.5.2
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: *id004
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rcov
|
80
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *id005
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rspec
|
93
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
segments:
|
99
|
+
- 2
|
100
|
+
- 4
|
101
|
+
- 0
|
102
|
+
version: 2.4.0
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: *id006
|
106
|
+
- !ruby/object:Gem::Dependency
|
107
|
+
name: bundler
|
108
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ~>
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
segments:
|
114
|
+
- 1
|
115
|
+
- 0
|
116
|
+
- 0
|
117
|
+
version: 1.0.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: *id007
|
121
|
+
- !ruby/object:Gem::Dependency
|
122
|
+
name: jeweler
|
123
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ~>
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
segments:
|
129
|
+
- 1
|
130
|
+
- 5
|
131
|
+
- 2
|
132
|
+
version: 1.5.2
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: *id008
|
136
|
+
- !ruby/object:Gem::Dependency
|
137
|
+
name: rcov
|
138
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
139
|
+
none: false
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
segments:
|
144
|
+
- 0
|
145
|
+
version: "0"
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: *id009
|
149
|
+
description: A basic proxy/delegate framework for Ruby that will allow you to wrap any object with a proxy instance. For more information about the Proxy and Delegate patterns, check out http://en.wikipedia.org/wiki/Proxy_pattern and http://en.wikipedia.org/wiki/Delegation_pattern respectively.
|
150
|
+
email: jacaetevha@gmail.com
|
151
|
+
executables: []
|
152
|
+
|
153
|
+
extensions: []
|
154
|
+
|
155
|
+
extra_rdoc_files:
|
156
|
+
- LICENSE.txt
|
157
|
+
- README.rdoc
|
158
|
+
files:
|
159
|
+
- Gemfile
|
160
|
+
- Gemfile.lock
|
161
|
+
- LICENSE.txt
|
162
|
+
- README.rdoc
|
163
|
+
- Rakefile
|
164
|
+
- VERSION
|
165
|
+
- lib/proxeze.rb
|
166
|
+
- proxeze.gemspec
|
167
|
+
- spec/definitions.rb
|
168
|
+
- spec/proxeze_spec.rb
|
169
|
+
- spec/spec_helper.rb
|
170
|
+
has_rdoc: true
|
171
|
+
homepage: http://github.com/jacaetevha/proxeze
|
172
|
+
licenses:
|
173
|
+
- MIT
|
174
|
+
post_install_message:
|
175
|
+
rdoc_options: []
|
176
|
+
|
177
|
+
require_paths:
|
178
|
+
- lib
|
179
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
180
|
+
none: false
|
181
|
+
requirements:
|
182
|
+
- - ">="
|
183
|
+
- !ruby/object:Gem::Version
|
184
|
+
hash: -2539751973325826461
|
185
|
+
segments:
|
186
|
+
- 0
|
187
|
+
version: "0"
|
188
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
189
|
+
none: false
|
190
|
+
requirements:
|
191
|
+
- - ">="
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
segments:
|
194
|
+
- 0
|
195
|
+
version: "0"
|
196
|
+
requirements: []
|
197
|
+
|
198
|
+
rubyforge_project:
|
199
|
+
rubygems_version: 1.3.7
|
200
|
+
signing_key:
|
201
|
+
specification_version: 3
|
202
|
+
summary: A basic proxy/delegate framework for Ruby that will allow you to wrap any object with a proxy instance.
|
203
|
+
test_files:
|
204
|
+
- spec/definitions.rb
|
205
|
+
- spec/proxeze_spec.rb
|
206
|
+
- spec/spec_helper.rb
|