Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Updated repository structure

Using Travic CI
  • Loading branch information...
commit d875236cfa59cc70840b8e4a4eda52860b6341e4 1 parent 747b391
Paul Engel authored
7 .travis.yml
... ... @@ -0,0 +1,7 @@
  1 +language: ruby
  2 +rvm:
  3 + - 1.9.3
  4 + - 1.9.2
  5 + - jruby-19mode
  6 + - 1.8.7
  7 + - ree
17 Gemfile
... ... @@ -1,3 +1,18 @@
1 1 source "http://rubygems.org"
2 2
3   -gemspec
  3 +gemspec
  4 +
  5 +group :gem_default do
  6 + gem "unextendable", :path => "."
  7 +end
  8 +
  9 +group :gem_development do
  10 + gem "pry"
  11 +end
  12 +
  13 +group :gem_test do
  14 + gem "minitest"
  15 + gem "mocha"
  16 + gem "pry"
  17 + gem "rake"
  18 +end
2  MIT-LICENSE
... ... @@ -1,4 +1,4 @@
1   -Copyright (c) 2011 Paul Engel
  1 +Copyright (c) 2012 Paul Engel
2 2
3 3 Permission is hereby granted, free of charge, to any person obtaining
4 4 a copy of this software and associated documentation files (the
2  README.textile
Source Rendered
... ... @@ -1,4 +1,4 @@
1   -h1. Unextendable
  1 +h1. Unextendable "!https://secure.travis-ci.org/archan937/unextendable.png!":http://travis-ci.org/archan937/unextendable
2 2
3 3 A small gem making unextending extended module methods within object instances possible
4 4
15 Rakefile
... ... @@ -1,10 +1,9 @@
1   -require "bundler"
2   -Bundler::GemHelper.install_tasks
3   -
  1 +#!/usr/bin/env rake
  2 +require "bundler/gem_tasks"
4 3 require "rake/testtask"
5   -Rake::TestTask.new(:test) do |test|
6   - test.pattern = "test/**/*_test.rb"
7   - test.verbose = true
8   -end
9 4
10   -task :default => :test
  5 +task :default => :test
  6 +
  7 +Rake::TestTask.new do |test|
  8 + test.pattern = "test/**/test_*.rb"
  9 +end
3  lib/core_ext.rb
... ... @@ -0,0 +1,3 @@
  1 +Dir["#{File.dirname(__FILE__)}/core_ext/*.rb"].sort.each do |path|
  2 + require path
  3 +end
0  lib/unextendable/kernel.rb → lib/core_ext/kernel.rb
File renamed without changes
0  lib/unextendable/module.rb → lib/core_ext/module.rb
File renamed without changes
0  lib/unextendable/object.rb → lib/core_ext/object.rb
File renamed without changes
6 lib/unextendable.rb
... ... @@ -1,4 +1,2 @@
1   -require File.expand_path("../unextendable/module" , __FILE__)
2   -require File.expand_path("../unextendable/kernel" , __FILE__)
3   -require File.expand_path("../unextendable/object" , __FILE__)
4   -require File.expand_path("../unextendable/version", __FILE__)
  1 +require "core_ext"
  2 +require "unextendable/version"
36 script/console
... ... @@ -1,2 +1,36 @@
1 1 #!/usr/bin/env ruby
2   -system "irb -r ./lib/unextendable.rb -r ./script/definitions.rb"
  2 +require "rubygems"
  3 +require "bundler"
  4 +
  5 +Bundler.require :gem_default, :gem_development
  6 +
  7 +puts "Loading Unextendable development environment (#{Unextendable::VERSION})"
  8 +puts "Defining classes ..."
  9 +puts "[0] pry(main)> @c = C.new; @c.title = \"Mr.\""
  10 +
  11 +module A
  12 + def name
  13 + "A"
  14 + end
  15 +end
  16 +
  17 +module U
  18 + unextendable
  19 + def name
  20 + "U"
  21 + end
  22 +end
  23 +
  24 +class C
  25 + attr_accessor :title
  26 + def salutation
  27 + [title, name].reject{|x| x.nil? || x.empty?}.join " "
  28 + end
  29 + def name
  30 + "C"
  31 + end
  32 +end
  33 +
  34 +@c = C.new
  35 +@c.title = "Mr."
  36 +Pry.start
25 script/definitions.rb
... ... @@ -1,25 +0,0 @@
1   -module A
2   - def name
3   - "A"
4   - end
5   -end
6   -
7   -module U
8   - unextendable
9   - def name
10   - "U"
11   - end
12   -end
13   -
14   -class C
15   - attr_accessor :title
16   - def salutation
17   - [title, name].reject{|x| x.nil? || x.empty?}.join " "
18   - end
19   - def name
20   - "C"
21   - end
22   -end
23   -
24   -@c = C.new
25   -@c.title = "Mr."
52 test/blank_object_test.rb
... ... @@ -1,52 +0,0 @@
1   -require File.expand_path("../test_helper", __FILE__)
2   -
3   -class BlankObjectTest < Test::Unit::TestCase
4   -
5   - # ==================================================================================================================================
6   - # A BlankObject class is considered not to have meta_class and unextend defined, but does respond to extend (e.g. Liquid::Strainer)
7   - # See also: http://rubydoc.info/gems/liquid/2.3.0/Liquid/Strainer
8   - # ==================================================================================================================================
9   -
10   - context "A blank object instance" do
11   - setup do
12   - module Hi
13   - unextendable
14   - def say_hi
15   - "Hi!"
16   - end
17   - end
18   - class BlankObject
19   - def meta_class
20   - raise NoMethodError
21   - end
22   - def unextend
23   - raise NoMethodError
24   - end
25   - def respond_to?(symbol, include_private = false)
26   - return false if %w(meta_class unextend).include? symbol.to_s
27   - super
28   - end
29   - end
30   - end
31   -
32   - should "have extend defined" do
33   - assert BlankObject.new.extend(Hi)
34   - end
35   -
36   - should "not have meta_class and unextend defined" do
37   - assert_raises NoMethodError do
38   - BlankObject.new.meta_class
39   - end
40   - assert_raises NoMethodError do
41   - BlankObject.new.unextend
42   - end
43   - end
44   -
45   - should "be extendable" do
46   - b = BlankObject.new
47   - b.extend Hi
48   - assert_equal "Hi!", b.say_hi
49   - end
50   - end
51   -
52   -end
41 test/module_test.rb
... ... @@ -1,41 +0,0 @@
1   -require File.expand_path("../test_helper", __FILE__)
2   -
3   -class ModuleTest < Test::Unit::TestCase
4   -
5   - context "A module" do
6   - setup do
7   - module A
8   - end
9   - end
10   -
11   - should "be able to be marked as unextendable" do
12   - assert A.respond_to?(:unextendable)
13   - end
14   -
15   - should "respond to :unextendable?" do
16   - assert A.respond_to?(:unextendable?)
17   - end
18   -
19   - context "which is not unextendable" do
20   - should "return false when asked to be unextendable" do
21   - assert !A.unextendable?
22   - end
23   - end
24   -
25   - context "which is unextendable" do
26   - setup do
27   - module U
28   - unextendable
29   - def name
30   - "U"
31   - end
32   - end
33   - end
34   -
35   - should "return true when asked to be unextendable" do
36   - assert U.unextendable?
37   - end
38   - end
39   - end
40   -
41   -end
307 test/object_test.rb
... ... @@ -1,307 +0,0 @@
1   -require File.expand_path("../test_helper", __FILE__)
2   -
3   -class ObjectTest < Test::Unit::TestCase
4   -
5   - context "An object instance" do
6   - setup do
7   - module A
8   - def name
9   - "A"
10   - end
11   - end
12   - class C
13   - attr_accessor :title
14   - def salutation
15   - [title, name].reject{|x| x.nil? || x.empty?}.join " "
16   - end
17   - def name
18   - "C"
19   - end
20   - private
21   - def id
22   - "C"
23   - end
24   - end
25   - @c = C.new
26   - @c.title = "Mr."
27   - end
28   -
29   - should "respond to meta_class and extended_modules" do
30   - assert @c.respond_to?(:meta_class)
31   - assert @c.meta_class.respond_to?(:extended_modules)
32   - end
33   -
34   - context "when extending modules" do
35   - should "check whether a module is unextendable or not" do
36   - module B; end
37   -
38   - A.expects(:unextendable?).twice
39   - B.expects(:unextendable?)
40   -
41   - @c.extend A
42   - @c.extend A, B
43   -
44   - assert @c.meta_class.included_modules.include?(A)
45   - assert @c.meta_class.included_modules.include?(B)
46   - end
47   -
48   - context "which are not unextendable" do
49   - should "behave as normal when the module is not unextendable" do
50   - A.expects(:wrap_unextendable_module).never
51   - @c.extend A
52   - assert @c.meta_class.included_modules.include?(A)
53   - assert @c.meta_class.extended_modules.include?(A)
54   - end
55   -
56   - should "behave as expected" do
57   - assert_equal "Mr. C", @c.salutation
58   -
59   - @c.extend A
60   - assert_equal "Mr. A", @c.salutation
61   -
62   - @c.unextend
63   - assert_equal "Mr. A", @c.salutation
64   -
65   - @d = C.new
66   - @d.title = "Mr."
67   - assert_equal "Mr. C", @d.salutation
68   -
69   - @d.extend A
70   - assert_equal "Mr. A", @d.salutation
71   -
72   - @d.unextend A
73   - assert_equal "Mr. A", @d.salutation
74   - end
75   - end
76   -
77   - context "which are unextendable" do
78   - setup do
79   - module B
80   - unextendable
81   - public
82   - def id
83   - "B"
84   - end
85   - end
86   -
87   - module U
88   - unextendable
89   - def name
90   - "U"
91   - end
92   - def foo
93   - "bar"
94   - end
95   - private
96   - def id
97   - "U"
98   - end
99   - end
100   - end
101   -
102   - should "respond to a non-extended instance method after extending" do
103   - assert @c.respond_to?(:salutation)
104   - @c.extend U
105   - assert @c.respond_to?(:salutation)
106   - end
107   -
108   - should "call wrap_unextendable_module" do
109   - @c.expects(:wrap_unextendable_module)
110   - @c.extend A, U
111   - end
112   -
113   - should "call wrap_unextendable_method" do
114   - @c.expects(:wrap_unextendable_method).times(3)
115   - @c.extend U
116   - end
117   -
118   - should "add nil value as method proc when not responding to module method name" do
119   - @c.extend U
120   - assert_equal 1, @c.meta_class.method_procs.select{|k, v| v.nil?}.size
121   - assert_equal 2, @c.meta_class.method_procs.select{|k, v| v.class == Proc}.size
122   - end
123   -
124   - should "add the module to extended_modules" do
125   - assert @c.meta_class.extended_modules.empty?
126   - @c.extend U
127   - assert @c.meta_class.extended_modules.include?(U)
128   - end
129   -
130   - should "add method proc to method_procs" do
131   - assert @c.meta_class.send(:method_procs).empty?
132   - @c.extend U
133   - assert_equal 3, @c.meta_class.send(:method_procs).size
134   - end
135   -
136   - context "when calling an unextendable method" do
137   - should "call call_unextendable_method" do
138   - @c.extend U
139   - @c.expects(:call_unextendable_method).with(:name)
140   - @c.name
141   - end
142   -
143   - should "call method_for" do
144   - method = @c.meta_class.instance_method(:name).bind(@c)
145   - @c.extend U
146   - @c.expects(:method_for).with(:name).returns(method)
147   - @c.name
148   - end
149   -
150   - should "match the expected method" do
151   - assert_equal @c.method(:name), @c.send(:method_for, :name)
152   - @c.extend U
153   - assert_equal U.instance_method(:name).bind(@c), @c.send(:method_for, :name)
154   - end
155   -
156   - should "return the expected value" do
157   - assert_equal "Mr. C", @c.salutation
158   - @c.extend U
159   - assert_equal "Mr. U", @c.salutation
160   -
161   - @d = C.new
162   - assert_equal "C", @d.salutation
163   - @d.extend U
164   - assert_equal "U", @d.salutation
165   - end
166   - end
167   -
168   - context "when unextending the module afterwards" do
169   - should "remove the module from extended_modules" do
170   - exception = assert_raises(NoMethodError) do
171   - @c.id
172   - end
173   - assert_equal "private method `id' called for", exception.message[0..29]
174   - assert_equal "C", @c.send(:id)
175   -
176   - @c.extend U
177   - assert @c.meta_class.extended_modules.include?(U)
178   - assert_equal "private method `id' called for", exception.message[0..29]
179   - assert_equal "U", @c.send(:id)
180   -
181   - @c.extend B
182   - assert_equal "B", @c.send(:id)
183   -
184   - @c.unextend
185   - assert !@c.meta_class.extended_modules.include?(U)
186   - assert_equal "private method `id' called for", exception.message[0..29]
187   - assert_equal "C", @c.send(:id)
188   - end
189   -
190   - should "remove the module but when passed a block only when it passes" do
191   - assert_equal "Mr. C", @c.salutation
192   -
193   - @c.extend U
194   - assert_equal "Mr. U", @c.salutation
195   -
196   - @c.unextend do |mod|
197   - mod != U
198   - end
199   - assert_equal "Mr. U", @c.salutation
200   -
201   - @c.unextend do |mod|
202   - mod == U
203   - end
204   - assert_equal "Mr. C", @c.salutation
205   - end
206   -
207   - context "when calling an unextendable method" do
208   - should "match the expected method" do
209   - assert_equal @c.method(:name), @c.send(:method_for, :name)
210   -
211   - @c.extend U
212   - assert_equal U.instance_method(:name).bind(@c), @c.send(:method_for, :name)
213   -
214   - @c.unextend U
215   - assert_equal Proc, @c.send(:method_for, :name).class
216   - end
217   -
218   - should "behave as expected" do
219   - assert_equal "Mr. C", @c.salutation
220   - @c.title = "Dr."
221   - assert_equal "Dr. C", @c.salutation
222   -
223   - assert !@c.respond_to?(:foo)
224   - assert_raise NoMethodError do
225   - @c.foo
226   - end
227   -
228   - @c.extend U
229   - assert_equal "Dr. U", @c.salutation
230   - @c.title = "Sir"
231   - assert_equal "Sir U", @c.salutation
232   -
233   - assert @c.respond_to?(:salutation)
234   - assert @c.respond_to?(:foo)
235   - assert_nothing_raised NoMethodError do
236   - @c.foo
237   - end
238   - assert_equal "bar", @c.foo
239   -
240   - @c.unextend U
241   - assert_equal "Sir C", @c.salutation
242   - @c.title = ""
243   - assert_equal "C", @c.salutation
244   -
245   - assert @c.respond_to?(:salutation)
246   - assert !@c.respond_to?(:foo)
247   - assert_raise NoMethodError do
248   - @c.foo
249   - end
250   -
251   - @c.extend U
252   - assert_equal "U", @c.salutation
253   - @c.title = "Ms."
254   - assert_equal "Ms. U", @c.salutation
255   -
256   - @c.unextend
257   - assert_equal "Ms. C", @c.salutation
258   -
259   - module D
260   - unextendable
261   - def name
262   - "D"
263   - end
264   - end
265   -
266   - @c.extend D
267   - assert_equal "Ms. D", @c.salutation
268   -
269   - @c.extend U
270   - assert_equal "Ms. U", @c.salutation
271   -
272   - @c.extend D
273   - assert_equal "Ms. D", @c.salutation
274   -
275   - @c.unextend
276   - assert_equal "Ms. C", @c.salutation
277   -
278   - @c.extend A
279   - assert_equal "Ms. A", @c.salutation
280   -
281   - @c.unextend
282   - assert_equal "Ms. A", @c.salutation
283   -
284   - @c.extend D
285   - assert_equal "Ms. D", @c.salutation
286   -
287   - @c.unextend
288   - assert_equal "Ms. A", @c.salutation
289   -
290   - @c.extend U
291   - @c.unextend do |mod|
292   - mod != U
293   - end
294   - assert_equal "Ms. U", @c.salutation
295   -
296   - @c.unextend do |mod|
297   - mod == U
298   - end
299   - assert_equal "Ms. A", @c.salutation
300   - end
301   - end
302   - end
303   - end
304   - end
305   - end
306   -
307   -end
12 test/test_helper.rb
... ... @@ -1,7 +1,7 @@
1   -$:.unshift File.expand_path("../../lib", __FILE__)
2   -
3 1 require "rubygems"
4   -require "test/unit"
5   -require "shoulda"
6   -require "mocha"
7   -require "unextendable"
  2 +require "bundler"
  3 +
  4 +require "minitest/unit"
  5 +require "minitest/autorun"
  6 +
  7 +Bundler.require :gem_default, :gem_test
54 test/unit/test_blank_object.rb
... ... @@ -0,0 +1,54 @@
  1 +require File.expand_path("../../test_helper", __FILE__)
  2 +
  3 +module Unit
  4 + class TestBlankObject < MiniTest::Unit::TestCase
  5 +
  6 + # ==================================================================================================================================
  7 + # A BlankObject class is considered not to have meta_class and unextend defined, but does respond to extend (e.g. Liquid::Strainer)
  8 + # See also: http://rubydoc.info/gems/liquid/2.3.0/Liquid/Strainer
  9 + # ==================================================================================================================================
  10 +
  11 + describe "A blank object instance" do
  12 + before do
  13 + module Hi
  14 + unextendable
  15 + def say_hi
  16 + "Hi!"
  17 + end
  18 + end
  19 + class BlankObject
  20 + def meta_class
  21 + raise NoMethodError
  22 + end
  23 + def unextend
  24 + raise NoMethodError
  25 + end
  26 + def respond_to?(symbol, include_private = false)
  27 + return false if %w(meta_class unextend).include? symbol.to_s
  28 + super
  29 + end
  30 + end
  31 + end
  32 +
  33 + it "should have extend defined" do
  34 + assert BlankObject.new.extend(Hi)
  35 + end
  36 +
  37 + it "should not have meta_class and unextend defined" do
  38 + assert_raises NoMethodError do
  39 + BlankObject.new.meta_class
  40 + end
  41 + assert_raises NoMethodError do
  42 + BlankObject.new.unextend
  43 + end
  44 + end
  45 +
  46 + it "should be extendable" do
  47 + b = BlankObject.new
  48 + b.extend Hi
  49 + assert_equal "Hi!", b.say_hi
  50 + end
  51 + end
  52 +
  53 + end
  54 +end
43 test/unit/test_module.rb
... ... @@ -0,0 +1,43 @@
  1 +require File.expand_path("../../test_helper", __FILE__)
  2 +
  3 +module Unit
  4 + class TestModule < MiniTest::Unit::TestCase
  5 +
  6 + describe "A module" do
  7 + before do
  8 + module A
  9 + end
  10 + end
  11 +
  12 + it "should be able to be marked as unextendable" do
  13 + assert A.respond_to?(:unextendable)
  14 + end
  15 +
  16 + it "should respond to :unextendable?" do
  17 + assert A.respond_to?(:unextendable?)
  18 + end
  19 +
  20 + describe "which is not unextendable" do
  21 + it "should return false when asked to be unextendable" do
  22 + assert !A.unextendable?
  23 + end
  24 + end
  25 +
  26 + describe "which is unextendable" do
  27 + before do
  28 + module U
  29 + unextendable
  30 + def name
  31 + "U"
  32 + end
  33 + end
  34 + end
  35 +
  36 + it "should return true when asked to be unextendable" do
  37 + assert U.unextendable?
  38 + end
  39 + end
  40 + end
  41 +
  42 + end
  43 +end
307 test/unit/test_object.rb
... ... @@ -0,0 +1,307 @@
  1 +require File.expand_path("../../test_helper", __FILE__)
  2 +
  3 +module Unit
  4 + class TestObject < MiniTest::Unit::TestCase
  5 +
  6 + describe "An object instance" do
  7 + before do
  8 + module A
  9 + def name
  10 + "A"
  11 + end
  12 + end
  13 + class C
  14 + attr_accessor :title
  15 + def salutation
  16 + [title, name].reject{|x| x.nil? || x.empty?}.join " "
  17 + end
  18 + def name
  19 + "C"
  20 + end
  21 + private
  22 + def id
  23 + "C"
  24 + end
  25 + end
  26 + @c = C.new
  27 + @c.title = "Mr."
  28 + end
  29 +
  30 + it "should respond to meta_class and extended_modules" do
  31 + assert @c.respond_to?(:meta_class)
  32 + assert @c.meta_class.respond_to?(:extended_modules)
  33 + end
  34 +
  35 + describe "when extending modules" do
  36 + it "should check whether a module is unextendable or not" do
  37 + module B; end
  38 +
  39 + A.expects(:unextendable?).twice
  40 + B.expects(:unextendable?)
  41 +
  42 + @c.extend A
  43 + @c.extend A, B
  44 +
  45 + assert @c.meta_class.included_modules.include?(A)
  46 + assert @c.meta_class.included_modules.include?(B)
  47 + end
  48 +
  49 + describe "which are not unextendable" do
  50 + it "should behave as normal when the module is not unextendable" do
  51 + A.expects(:wrap_unextendable_module).never
  52 + @c.extend A
  53 + assert @c.meta_class.included_modules.include?(A)
  54 + assert @c.meta_class.extended_modules.include?(A)
  55 + end
  56 +
  57 + it "should behave as expected" do
  58 + assert_equal "Mr. C", @c.salutation
  59 +
  60 + @c.extend A
  61 + assert_equal "Mr. A", @c.salutation
  62 +
  63 + @c.unextend
  64 + assert_equal "Mr. A", @c.salutation
  65 +
  66 + @d = C.new
  67 + @d.title = "Mr."
  68 + assert_equal "Mr. C", @d.salutation
  69 +
  70 + @d.extend A
  71 + assert_equal "Mr. A", @d.salutation
  72 +
  73 + @d.unextend A
  74 + assert_equal "Mr. A", @d.salutation
  75 + end
  76 + end
  77 +
  78 + describe "which are unextendable" do
  79 + before do
  80 + module B
  81 + unextendable
  82 + public
  83 + def id
  84 + "B"
  85 + end
  86 + end
  87 +
  88 + module U
  89 + unextendable
  90 + def name
  91 + "U"
  92 + end
  93 + def foo
  94 + "bar"
  95 + end
  96 + private
  97 + def id
  98 + "U"
  99 + end
  100 + end
  101 + end
  102 +
  103 + it "should respond to a non-extended instance method after extending" do
  104 + assert @c.respond_to?(:salutation)
  105 + @c.extend U
  106 + assert @c.respond_to?(:salutation)
  107 + end
  108 +
  109 + it "should call wrap_unextendable_module" do
  110 + @c.expects(:wrap_unextendable_module)
  111 + @c.extend A, U
  112 + end
  113 +
  114 + it "should call wrap_unextendable_method" do
  115 + @c.expects(:wrap_unextendable_method).times(3)
  116 + @c.extend U
  117 + end
  118 +
  119 + it "should add nil value as method proc when not responding to module method name" do
  120 + @c.extend U
  121 + assert_equal 1, @c.meta_class.method_procs.select{|k, v| v.nil?}.size
  122 + assert_equal 2, @c.meta_class.method_procs.select{|k, v| v.class == Proc}.size
  123 + end
  124 +
  125 + it "should add the module to extended_modules" do
  126 + assert @c.meta_class.extended_modules.empty?
  127 + @c.extend U
  128 + assert @c.meta_class.extended_modules.include?(U)
  129 + end
  130 +
  131 + it "should add method proc to method_procs" do
  132 + assert @c.meta_class.send(:method_procs).empty?
  133 + @c.extend U
  134 + assert_equal 3, @c.meta_class.send(:method_procs).size
  135 + end
  136 +
  137 + describe "when calling an unextendable method" do
  138 + it "should call call_unextendable_method" do
  139 + @c.extend U
  140 + @c.expects(:call_unextendable_method).with(:name)
  141 + @c.name
  142 + end
  143 +
  144 + it "should call method_for" do
  145 + method = @c.meta_class.instance_method(:name).bind(@c)
  146 + @c.extend U
  147 + @c.expects(:method_for).with(:name).returns(method)
  148 + @c.name
  149 + end
  150 +
  151 + it "should match the expected method" do
  152 + assert_equal @c.method(:name), @c.send(:method_for, :name)
  153 + @c.extend U
  154 + assert_equal U.instance_method(:name).bind(@c), @c.send(:method_for, :name)
  155 + end
  156 +
  157 + it "should return the expected value" do
  158 + assert_equal "Mr. C", @c.salutation
  159 + @c.extend U
  160 + assert_equal "Mr. U", @c.salutation
  161 +
  162 + @d = C.new
  163 + assert_equal "C", @d.salutation
  164 + @d.extend U
  165 + assert_equal "U", @d.salutation
  166 + end
  167 + end
  168 +
  169 + describe "when unextending the module afterwards" do
  170 + it "should remove the module from extended_modules" do
  171 + exception = assert_raises(NoMethodError) do
  172 + @c.id
  173 + end
  174 + assert_equal "private method `id' called for", exception.message[0..29]
  175 + assert_equal "C", @c.send(:id)
  176 +
  177 + @c.extend U
  178 + assert @c.meta_class.extended_modules.include?(U)
  179 + assert_equal "private method `id' called for", exception.message[0..29]
  180 + assert_equal "U", @c.send(:id)
  181 +
  182 + @c.extend B
  183 + assert_equal "B", @c.send(:id)
  184 +
  185 + @c.unextend
  186 + assert !@c.meta_class.extended_modules.include?(U)
  187 + assert_equal "private method `id' called for", exception.message[0..29]
  188 + assert_equal "C", @c.send(:id)
  189 + end
  190 +
  191 + it "should remove the module but when passed a block only when it passes" do
  192 + assert_equal "Mr. C", @c.salutation
  193 +
  194 + @c.extend U
  195 + assert_equal "Mr. U", @c.salutation
  196 +
  197 + @c.unextend do |mod|
  198 + mod != U
  199 + end
  200 + assert_equal "Mr. U", @c.salutation
  201 +
  202 + @c.unextend do |mod|
  203 + mod == U
  204 + end
  205 + assert_equal "Mr. C", @c.salutation
  206 + end
  207 +
  208 + describe "when calling an unextendable method" do
  209 + it "should match the expected method" do
  210 + assert_equal @c.method(:name), @c.send(:method_for, :name)
  211 +
  212 + @c.extend U
  213 + assert_equal U.instance_method(:name).bind(@c), @c.send(:method_for, :name)
  214 +
  215 + @c.unextend U
  216 + assert_equal Proc, @c.send(:method_for, :name).class
  217 + end
  218 +
  219 + it "should behave as expected" do
  220 + assert_equal "Mr. C", @c.salutation
  221 + @c.title = "Dr."
  222 + assert_equal "Dr. C", @c.salutation
  223 +
  224 + assert !@c.respond_to?(:foo)
  225 + assert_raises NoMethodError do
  226 + @c.foo
  227 + end
  228 +
  229 + @c.extend U
  230 + assert_equal "Dr. U", @c.salutation
  231 + @c.title = "Sir"
  232 + assert_equal "Sir U", @c.salutation
  233 +
  234 + assert @c.respond_to?(:salutation)
  235 + assert @c.respond_to?(:foo)
  236 + @c.foo
  237 + assert_equal "bar", @c.foo
  238 +
  239 + @c.unextend U
  240 + assert_equal "Sir C", @c.salutation
  241 + @c.title = ""
  242 + assert_equal "C", @c.salutation
  243 +
  244 + assert @c.respond_to?(:salutation)
  245 + assert !@c.respond_to?(:foo)
  246 + assert_raises NoMethodError do
  247 + @c.foo
  248 + end
  249 +
  250 + @c.extend U
  251 + assert_equal "U", @c.salutation
  252 + @c.title = "Ms."
  253 + assert_equal "Ms. U", @c.salutation
  254 +
  255 + @c.unextend
  256 + assert_equal "Ms. C", @c.salutation
  257 +
  258 + module D
  259 + unextendable
  260 + def name
  261 + "D"
  262 + end
  263 + end
  264 +
  265 + @c.extend D
  266 + assert_equal "Ms. D", @c.salutation
  267 +
  268 + @c.extend U
  269 + assert_equal "Ms. U", @c.salutation
  270 +
  271 + @c.extend D
  272 + assert_equal "Ms. D", @c.salutation
  273 +
  274 + @c.unextend
  275 + assert_equal "Ms. C", @c.salutation
  276 +
  277 + @c.extend A
  278 + assert_equal "Ms. A", @c.salutation
  279 +
  280 + @c.unextend
  281 + assert_equal "Ms. A", @c.salutation
  282 +
  283 + @c.extend D
  284 + assert_equal "Ms. D", @c.salutation
  285 +
  286 + @c.unextend
  287 + assert_equal "Ms. A", @c.salutation
  288 +
  289 + @c.extend U
  290 + @c.unextend do |mod|
  291 + mod != U
  292 + end
  293 + assert_equal "Ms. U", @c.salutation
  294 +
  295 + @c.unextend do |mod|
  296 + mod == U
  297 + end
  298 + assert_equal "Ms. A", @c.salutation
  299 + end
  300 + end
  301 + end
  302 + end
  303 + end
  304 + end
  305 +
  306 + end
  307 +end
33 unextendable.gemspec
... ... @@ -1,24 +1,19 @@
1 1 # -*- encoding: utf-8 -*-
  2 +
2 3 $:.push File.expand_path("../lib", __FILE__)
3 4 require "unextendable/version"
4 5
5   -Gem::Specification.new do |s|
6   - s.name = "unextendable"
7   - s.version = Unextendable::VERSION
8   - s.platform = Gem::Platform::RUBY
9   - s.authors = ["Paul Engel"]
10   - s.email = ["paul.engel@holder.nl"]
11   - s.homepage = "https://github.com/archan937/unextendable"
12   - s.summary = %q{A small gem making unextending extended module methods within object instances possible}
13   - s.description = %q{Unextendable originated from the thought of being able to implement the State pattern within object instances using modules. In other words: I wanted object instances to behave dependent on their state using modules. I really want to use modules because they are commonly used to define a set of methods which you can extend within an object instance. Unfortunately, you cannot just unexclude a module. So after searching the web for solutions, I came across Mixology, evil-ruby and StatePattern. But they slightly did not fit the picture. So after doing some research, I came up with Unextendable.}
14   -
15   - s.rubyforge_project = "unextendable"
16   -
17   - s.files = `git ls-files`.split("\n")
18   - s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19   - s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20   - s.require_paths = ["lib"]
  6 +Gem::Specification.new do |gem|
  7 + gem.authors = ["Paul Engel"]
  8 + gem.email = ["paul.engel@holder.nl"]
  9 + gem.summary = %q{A small gem making unextending extended module methods within object instances possible}
  10 + gem.description = %q{Unextendable originated from the thought of being able to implement the State pattern within object instances using modules. In other words: I wanted object instances to behave dependent on their state using modules. I really want to use modules because they are commonly used to define a set of methods which you can extend within an object instance. Unfortunately, you cannot just unexclude a module. So after searching the web for solutions, I came across Mixology, evil-ruby and StatePattern. But they slightly did not fit the picture. So after doing some research, I came up with Unextendable.}
  11 + gem.homepage = "https://github.com/archan937/unextendable"
21 12
22   - s.add_development_dependency "shoulda"
23   - s.add_development_dependency "mocha"
24   -end
  13 + gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
  14 + gem.files = `git ls-files`.split("\n")
  15 + gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
  16 + gem.name = "unextendable"
  17 + gem.require_paths = ["lib"]
  18 + gem.version = Unextendable::VERSION
  19 +end

0 comments on commit d875236

Please sign in to comment.
Something went wrong with that request. Please try again.