dumb_delegator 0.0.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.
@@ -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