dumb_delegator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ --order rand
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - jruby-19mode
6
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dumb_delegator.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Andy Lindeman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,112 @@
1
+ # DumbDelegator
2
+
3
+ [![Build Status](https://secure.travis-ci.org/highgroove/dumb_delegator.png)](http://travis-ci.org/highgroove/dumb_delegator)
4
+
5
+ Ruby provides the `delegate` standard library. However, we found that it is
6
+ not appropriate for many use cases that require nearly every call to be
7
+ proxied.
8
+
9
+ For instance, Rails uses `#class` and `#instance_of?` to introspect on model
10
+ classes when generating forms and URL helpers. These methods are not forwarded
11
+ when using `Delegator` or `SimpleDelegator`.
12
+
13
+ ```ruby
14
+ require 'delegate'
15
+
16
+ class MyAwesomeClass
17
+ # ...
18
+ end
19
+
20
+ o = MyAwesomeClass.new
21
+ d = SimpleDelegator.new(o)
22
+
23
+ d.class # => SimpleDelegator
24
+ d.is_a? MyAwesomeClass # => false
25
+ ```
26
+
27
+ `DumbDelegator`, on the other hand, forwards almost ALL the things:
28
+
29
+ ```ruby
30
+ require 'dumb_delegator'
31
+
32
+ class MyAwesomeClass
33
+ # ...
34
+ end
35
+
36
+ o = MyAwesomeClass.new
37
+ d = DumbDelegator.new(o)
38
+
39
+ d.class # => MyAwesomeClass
40
+ d.is_a? MyAwesomeClass # => true
41
+ ```
42
+
43
+ ## Usage
44
+
45
+ ### Rails Model Decorator
46
+
47
+ There are [many decorator
48
+ implementations](http://robots.thoughtbot.com/post/14825364877/evaluating-alternative-decorator-implementations-in)
49
+ in Ruby. One of the simplest is "SimpleDelegator + super + getobj," but it has
50
+ the drawback of confusing Rails. It is necessary to redefine `class`. We've
51
+ also observed the need to redefine `instance_of?` for URL helpers.
52
+
53
+ With `DumbDelegator`, there's not a need for this hackery because nearly every
54
+ possible method is delegated:
55
+
56
+ ```ruby
57
+ require 'dumb_delegator'
58
+
59
+ class Coffee
60
+ def cost
61
+ 2
62
+ end
63
+
64
+ def origin
65
+ "Colombia"
66
+ end
67
+ end
68
+
69
+ class Milk < DumbDelegator
70
+ def cost
71
+ super + 0.4
72
+ end
73
+ end
74
+
75
+ class Sugar < DumbDelegator
76
+ def cost
77
+ super + 0.2
78
+ end
79
+ end
80
+
81
+ coffee = Coffee.new
82
+ Sugar.new(Milk.new(coffee)).cost # 2.6
83
+ Sugar.new(Sugar.new(coffee)).cost # 2.4
84
+ Milk.new(coffee).origin # Colombia
85
+ Sugar.new(Milk.new(coffee)).class # Coffee
86
+ ```
87
+
88
+ ## Installation
89
+
90
+ Add this line to your application's Gemfile:
91
+
92
+ gem 'dumb_delegator'
93
+
94
+ And then execute:
95
+
96
+ $ bundle
97
+
98
+ Or install it yourself as:
99
+
100
+ $ gem install dumb_delegator
101
+
102
+ ## Contributing
103
+
104
+ 1. Fork it
105
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
106
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
107
+ 4. Push to the branch (`git push origin my-new-feature`)
108
+ 5. Create new Pull Request
109
+
110
+ ## Contribution Ideas/Needs
111
+
112
+ 1. Ruby 1.8 support (use the `blankslate` gem?)
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec) do |t|
6
+ t.rspec_opts = "--tag ~objectspace" if RUBY_PLATFORM == "java"
7
+ end
8
+
9
+ task :default => :spec
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/dumb_delegator/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Andy Lindeman"]
6
+ gem.email = ["andy@highgroove.com"]
7
+ gem.description = %q{Delegator class that delegates ALL the things}
8
+ gem.summary = <<-EOD
9
+ Delegator and SimpleDelegator in Ruby's stdlib are somewhat useful, but they pull in most of Kernel. This is not appropriate for many uses; for instance, delegation to Rails models.
10
+ EOD
11
+ gem.homepage = "https://github.com/highgroove/dumb_delegator"
12
+
13
+ gem.files = `git ls-files`.split($\)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.name = "dumb_delegator"
17
+ gem.require_paths = ["lib"]
18
+ gem.version = DumbDelegator::VERSION
19
+
20
+ gem.add_development_dependency 'rspec', '~>2.9.0'
21
+ gem.add_development_dependency 'pry'
22
+ gem.add_development_dependency 'rake'
23
+ end
@@ -0,0 +1,65 @@
1
+ require "dumb_delegator/version"
2
+
3
+ class DumbDelegator < ::BasicObject
4
+ (::BasicObject.instance_methods - [:equal?, :__id__, :__send__, :method_missing]).each do |method|
5
+ undef_method method
6
+ end
7
+
8
+ kernel = ::Kernel.dup
9
+ (kernel.instance_methods - [:dup, :clone]).each do |method|
10
+ kernel.__send__ :undef_method, method
11
+ end
12
+ include kernel
13
+
14
+ NON_DELEGATED_METHODS = [:equal?, :__id__, :__send__, :dup, :clone, :__getobj__, :__setobj__,
15
+ :marshal_dump, :marshal_load, :respond_to?].freeze
16
+
17
+ def initialize(target)
18
+ __setobj__(target)
19
+ end
20
+
21
+ def respond_to?(method)
22
+ __getobj__.respond_to?(method) || NON_DELEGATED_METHODS.include?(method.to_sym)
23
+ end
24
+
25
+ def method_missing(method, *args, &block)
26
+ if @__dumb_target__.respond_to?(method)
27
+ @__dumb_target__.__send__(method, *args, &block)
28
+ else
29
+ super
30
+ end
31
+ end
32
+
33
+ def __getobj__
34
+ @__dumb_target__
35
+ end
36
+
37
+ def __setobj__(obj)
38
+ @__dumb_target__ = obj
39
+ end
40
+
41
+ def marshal_dump
42
+ [
43
+ :__v1__,
44
+ __getobj__
45
+ ]
46
+ end
47
+
48
+ def marshal_load(data)
49
+ version, obj = data
50
+ case version
51
+ when :__v1__
52
+ __setobj__(obj)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def initialize_dup(obj)
59
+ __setobj__(obj.__getobj__.dup)
60
+ end
61
+
62
+ def initialize_clone(obj)
63
+ __setobj__(obj.__getobj__.clone)
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ class DumbDelegator < ::BasicObject
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,140 @@
1
+ require "spec_helper"
2
+
3
+ describe DumbDelegator do
4
+ let(:target) { double }
5
+ subject { described_class.new(target) }
6
+
7
+ it "delegates to the target object" do
8
+ target.should_receive(:foo)
9
+ subject.foo
10
+ end
11
+
12
+ it "delegates to the target object with arguments" do
13
+ target.should_receive(:foo).with(:bar)
14
+
15
+ subject.foo(:bar)
16
+ end
17
+
18
+ it "delegates to the target object with a block" do
19
+ bar_block = proc { "bar" }
20
+ target.should_receive(:foo) { |&block| block.should == bar_block }
21
+
22
+ subject.foo(&bar_block)
23
+ end
24
+
25
+ it "does not delegate if the target does not respond_to? the message" do
26
+ target.stub(:foo)
27
+ target.stub(:respond_to?).with(:foo).and_return(false)
28
+
29
+ expect {
30
+ subject.foo
31
+ }.to raise_error(NoMethodError)
32
+ end
33
+
34
+ it "responds to methods defined by child classes that add behavior" do
35
+ target.should_receive(:foo).never
36
+ def subject.foo
37
+ "bar"
38
+ end
39
+
40
+ subject.foo
41
+ end
42
+
43
+ it "delegates methods defined on Object" do
44
+ target.should_receive(:class)
45
+ subject.class
46
+ end
47
+
48
+ it "delegates is_a?" do
49
+ target.should_receive(:is_a?)
50
+ subject.is_a?
51
+ end
52
+
53
+ it "delegates methods defined on Kernel" do
54
+ target.should_receive(:print)
55
+ subject.print
56
+ end
57
+
58
+ it "delegates !" do
59
+ target.should_receive(:!)
60
+ !subject
61
+ end
62
+
63
+ it "delegates !=" do
64
+ target.should_receive(:!=)
65
+ subject != 1
66
+ end
67
+
68
+ it "delegates ==" do
69
+ target.should_receive(:==)
70
+ subject == 1
71
+ end
72
+
73
+ it "delegates ==" do
74
+ target.should_receive(:==)
75
+ subject == 1
76
+ end
77
+
78
+ it "delegates instance_eval" do
79
+ target.should_receive(:instance_eval)
80
+ subject.instance_eval { true }
81
+ end
82
+
83
+ it "delegates instance_exec" do
84
+ target.should_receive(:instance_exec)
85
+ subject.instance_exec { true }
86
+ end
87
+
88
+ describe "#dup" do
89
+ it "returns a shallow of itself, the delegator (not the underlying object)", :objectspace => true do
90
+ dupped = subject.dup
91
+
92
+ ObjectSpace.each_object(DumbDelegator).map(&:__id__).should include dupped.__id__
93
+ end
94
+ end
95
+
96
+ describe "#clone" do
97
+ it "returns a shallow of itself, the delegator (not the underlying object)", :objectspace => true do
98
+ cloned = subject.clone
99
+
100
+ ObjectSpace.each_object(DumbDelegator).map(&:__id__).should include cloned.__id__
101
+ end
102
+ end
103
+
104
+ describe "marshaling" do
105
+ let(:target) { Object.new }
106
+
107
+ it "marshals and unmarshals itself, the delegator (not the underlying object)", :objectspace => true do
108
+ marshaled = Marshal.dump(subject)
109
+ unmarshaled = Marshal.load(marshaled)
110
+
111
+ ObjectSpace.each_object(DumbDelegator).map(&:__id__).should include unmarshaled.__id__
112
+ end
113
+ end
114
+
115
+ describe "#respond_to?" do
116
+ [:equal?, :__id__, :__send__, :dup, :clone, :__getobj__, :__setobj__, :marshal_dump, :marshal_load, :respond_to?].each do |method|
117
+ it "responds to #{method}" do
118
+ subject.respond_to?(method).should be_true
119
+ end
120
+ end
121
+ end
122
+
123
+ describe "#__getobj__" do
124
+ it "returns the target object" do
125
+ subject.__getobj__.should equal target
126
+ end
127
+ end
128
+
129
+ describe "#__setobj__" do
130
+ it "resets the target object to a different object" do
131
+ target.should_receive(:foo).never
132
+
133
+ new_target = double
134
+ new_target.should_receive(:foo)
135
+
136
+ subject.__setobj__(new_target)
137
+ subject.foo
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,16 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+ require File.expand_path('../lib/dumb_delegator', File.dirname(__FILE__))
9
+
10
+ require 'pry'
11
+
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ config.run_all_when_everything_filtered = true
15
+ config.filter_run :focus
16
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dumb_delegator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andy Lindeman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70229738467520 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.9.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70229738467520
25
+ - !ruby/object:Gem::Dependency
26
+ name: pry
27
+ requirement: &70229738467060 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70229738467060
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &70229738466500 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70229738466500
47
+ description: Delegator class that delegates ALL the things
48
+ email:
49
+ - andy@highgroove.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - .rspec
56
+ - .travis.yml
57
+ - Gemfile
58
+ - LICENSE
59
+ - README.md
60
+ - Rakefile
61
+ - dumb_delegator.gemspec
62
+ - lib/dumb_delegator.rb
63
+ - lib/dumb_delegator/version.rb
64
+ - spec/dumb_delegator_spec.rb
65
+ - spec/spec_helper.rb
66
+ homepage: https://github.com/highgroove/dumb_delegator
67
+ licenses: []
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ segments:
79
+ - 0
80
+ hash: -1320579537575582950
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ segments:
88
+ - 0
89
+ hash: -1320579537575582950
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 1.8.15
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: Delegator and SimpleDelegator in Ruby's stdlib are somewhat useful, but they
96
+ pull in most of Kernel. This is not appropriate for many uses; for instance, delegation
97
+ to Rails models.
98
+ test_files:
99
+ - spec/dumb_delegator_spec.rb
100
+ - spec/spec_helper.rb