up_the_irons-immutable 0.2 → 0.3
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.
- data/README +12 -4
- data/immutable.gemspec +9 -10
- data/lib/immutable.rb +36 -16
- data/spec/immutable_spec.rb +74 -9
- metadata +6 -4
data/README
CHANGED
@@ -3,8 +3,8 @@ Immutable
|
|
3
3
|
=========
|
4
4
|
|
5
5
|
:Author: Garry Dolley
|
6
|
-
:Date: 09-
|
7
|
-
:Version: v0.
|
6
|
+
:Date: 09-21-2008
|
7
|
+
:Version: v0.2
|
8
8
|
|
9
9
|
The ``Immutable`` module provides a method (immutable_method) that let's one
|
10
10
|
declare method(s) as immutable. That is, other code will not be able to
|
@@ -22,7 +22,12 @@ Alpha
|
|
22
22
|
This code is very new and despite a pretty comprehensive spec, I'm sure there's
|
23
23
|
cases where someone can figure out how to defeat this. So be it. :)
|
24
24
|
|
25
|
-
|
25
|
+
This code has been tested on the following systems:
|
26
|
+
|
27
|
+
* GNU/Linux (Ubuntu 8.04.1) with Ruby 1.8.6
|
28
|
+
* FreeBSD 7.0 with Ruby 1.8.6
|
29
|
+
* OpenBSD 4.3 with Ruby 1.8.6
|
30
|
+
* Mac OS X 10.5 with Ruby 1.8.6
|
26
31
|
|
27
32
|
Please see the Author section below and report any problems.
|
28
33
|
|
@@ -177,6 +182,9 @@ Use whichever style you prefer.
|
|
177
182
|
To Do
|
178
183
|
-----
|
179
184
|
|
185
|
+
Make method_added immutable, as well as immutable_method. Write tests to try
|
186
|
+
to "defeat" an immutable method, see if we can prevent it.
|
187
|
+
|
180
188
|
I finished my TODOs, cool.
|
181
189
|
|
182
190
|
Author
|
@@ -204,7 +212,7 @@ look like markup, even though it is.
|
|
204
212
|
Copyright
|
205
213
|
---------
|
206
214
|
|
207
|
-
Copyright (c) 2008 Garry C. Dolley
|
215
|
+
Copyright (c) 2008,2009 Garry C. Dolley
|
208
216
|
|
209
217
|
Immutable is free software; you can redistribute it and/or modify it under the
|
210
218
|
terms of the GNU General Public License as published by the Free Software
|
data/immutable.gemspec
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
spec = Gem::Specification.new do |s|
|
2
|
-
s.name
|
3
|
-
s.version
|
4
|
-
s.
|
5
|
-
s.email
|
6
|
-
s.homepage
|
7
|
-
s.
|
8
|
-
s.summary
|
9
|
-
|
10
|
-
s.
|
11
|
-
s.has_rdoc = false
|
2
|
+
s.name = "immutable"
|
3
|
+
s.version = "0.3"
|
4
|
+
s.authors = ["Garry Dolley", "Lucas de Castro"]
|
5
|
+
s.email = "gdolley@ucla.edu"
|
6
|
+
s.homepage = "http://github.com/up_the_irons/immutable/tree/master"
|
7
|
+
s.description = "Declare methods as immutable."
|
8
|
+
s.summary = "Declare methods as immutable, somewhat like Java's 'final' keyword but still allowing child classes to override."
|
9
|
+
s.files = ['lib/immutable.rb', 'spec/immutable_spec.rb', 'immutable.gemspec', 'README', 'COPYING']
|
10
|
+
s.has_rdoc = false
|
12
11
|
end
|
data/lib/immutable.rb
CHANGED
@@ -1,36 +1,50 @@
|
|
1
1
|
module Immutable
|
2
2
|
class CannotOverrideMethod < StandardError; end
|
3
3
|
|
4
|
+
# Random ID changed at each interpreter load
|
5
|
+
UNIQ = "_#{object_id.abs}"
|
6
|
+
|
4
7
|
def self.included(mod)
|
5
8
|
mod.extend(ClassMethods)
|
6
9
|
end
|
7
10
|
|
8
11
|
module ClassMethods
|
9
12
|
def immutable_method(*args)
|
13
|
+
# Initialize variables
|
14
|
+
@immutable_methods = [] if @immutable_methods.nil?
|
15
|
+
@silent_immutable_methods = [] if @silent_immutable_methods.nil?
|
16
|
+
instance_variable_set("@#{UNIQ}_in_method_added", false)
|
17
|
+
|
10
18
|
opts = args.last.is_a?(Hash) ? args.pop : {}
|
11
19
|
|
12
20
|
args.each do |method|
|
13
|
-
alias_method "
|
21
|
+
alias_method "#{UNIQ}_old_#{method}", method
|
14
22
|
end
|
23
|
+
|
24
|
+
# Build list of immutable methods
|
25
|
+
@immutable_methods += args
|
26
|
+
@silent_immutable_methods += args if opts[:silent]
|
15
27
|
|
16
|
-
@
|
28
|
+
@opts = opts
|
17
29
|
module_eval do
|
18
30
|
def self.method_added(sym)
|
19
|
-
if @
|
20
|
-
@
|
21
|
-
if method && sym == method.to_sym && !
|
22
|
-
unless @
|
31
|
+
if @immutable_methods
|
32
|
+
@immutable_methods.each do |method|
|
33
|
+
if method && sym == method.to_sym && !in_method_added?
|
34
|
+
unless @silent_immutable_methods.include?(method)
|
23
35
|
raise CannotOverrideMethod, "Cannot override the immutable method: #{sym}"
|
24
36
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
37
|
+
|
38
|
+
allow_method_override do
|
39
|
+
self.module_eval <<-"end;"
|
40
|
+
def #{method}(*args, &block)
|
41
|
+
#{UNIQ}_old_#{method}(*args, &block)
|
42
|
+
end
|
43
|
+
end;
|
44
|
+
end
|
31
45
|
end
|
32
46
|
end # @args.each
|
33
|
-
end # @
|
47
|
+
end # @immutable_methods
|
34
48
|
end # def self.method_added()
|
35
49
|
|
36
50
|
def self.method_undefined(sym)
|
@@ -42,9 +56,15 @@ module Immutable
|
|
42
56
|
end
|
43
57
|
end # module_eval
|
44
58
|
|
45
|
-
def self.
|
46
|
-
|
47
|
-
|
59
|
+
def self.allow_method_override
|
60
|
+
instance_variable_set("@#{UNIQ}_in_method_added", true)
|
61
|
+
yield
|
62
|
+
ensure
|
63
|
+
instance_variable_set("@#{UNIQ}_in_method_added", false)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.in_method_added?
|
67
|
+
instance_variable_get("@#{UNIQ}_in_method_added")
|
48
68
|
end
|
49
69
|
end # def immutable_method()
|
50
70
|
|
data/spec/immutable_spec.rb
CHANGED
@@ -27,15 +27,6 @@ Foo2 = Foo.clone
|
|
27
27
|
Foo3 = Foo.clone
|
28
28
|
|
29
29
|
describe "Module Foo" do
|
30
|
-
def test_it(mod, method)
|
31
|
-
@value = Object.instance_eval do
|
32
|
-
include mod
|
33
|
-
send(method)
|
34
|
-
end
|
35
|
-
|
36
|
-
@value.should == :fast
|
37
|
-
end
|
38
|
-
|
39
30
|
describe "after redefining" do
|
40
31
|
it "should not let foo() be redefined" do
|
41
32
|
redefine(Foo, :foo)
|
@@ -185,6 +176,11 @@ module Boo
|
|
185
176
|
:fast
|
186
177
|
end
|
187
178
|
|
179
|
+
def boofoo
|
180
|
+
:boofoo_fast
|
181
|
+
end
|
182
|
+
|
183
|
+
immutable_method :boofoo, :silent => true
|
188
184
|
immutable_method :boo
|
189
185
|
end
|
190
186
|
|
@@ -196,6 +192,66 @@ describe "Exceptions" do
|
|
196
192
|
end.should raise_error(Immutable::CannotOverrideMethod, /Cannot override the immutable method: boo$/)
|
197
193
|
end
|
198
194
|
end
|
195
|
+
|
196
|
+
it "should not raise if :silent => true" do
|
197
|
+
redefine(Boo, :boofoo)
|
198
|
+
test_it(Boo, :boofoo, :boofoo_fast)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
#########
|
203
|
+
# Other #
|
204
|
+
#########
|
205
|
+
|
206
|
+
module Bear
|
207
|
+
include Immutable
|
208
|
+
|
209
|
+
def foo
|
210
|
+
:foo_fast
|
211
|
+
end
|
212
|
+
|
213
|
+
def bar
|
214
|
+
:bar_fast
|
215
|
+
end
|
216
|
+
|
217
|
+
def baz
|
218
|
+
:baz_fast
|
219
|
+
end
|
220
|
+
|
221
|
+
def boo
|
222
|
+
:boo_fast
|
223
|
+
end
|
224
|
+
|
225
|
+
# Make sure we can make independent calls to immutable_method
|
226
|
+
immutable_method :foo
|
227
|
+
immutable_method :bar
|
228
|
+
immutable_method :baz, :silent => true
|
229
|
+
immutable_method :boo
|
230
|
+
end
|
231
|
+
|
232
|
+
describe "Multiple independent calls to immutable_method()" do
|
233
|
+
it "should still recognize foo() is immutable" do
|
234
|
+
lambda do
|
235
|
+
redefine(Bear, :foo)
|
236
|
+
end.should raise_error(Immutable::CannotOverrideMethod, /Cannot override the immutable method: foo$/)
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should still recognize bar() is immutable" do
|
240
|
+
lambda do
|
241
|
+
redefine(Bear, :bar)
|
242
|
+
end.should raise_error(Immutable::CannotOverrideMethod, /Cannot override the immutable method: bar$/)
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should still recognize baz() is immutable" do
|
246
|
+
redefine(Bear, :baz)
|
247
|
+
test_it(Bear, :baz, :baz_fast)
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should still recognize boo() is immutable" do
|
251
|
+
lambda do
|
252
|
+
redefine(Bear, :boo)
|
253
|
+
end.should raise_error(Immutable::CannotOverrideMethod, /Cannot override the immutable method: boo$/)
|
254
|
+
end
|
199
255
|
end
|
200
256
|
|
201
257
|
##################
|
@@ -221,3 +277,12 @@ def remove(mod, method)
|
|
221
277
|
remove_method(method)
|
222
278
|
end
|
223
279
|
end
|
280
|
+
|
281
|
+
def test_it(mod, method, value = :fast)
|
282
|
+
@value = Object.instance_eval do
|
283
|
+
include mod
|
284
|
+
send(method)
|
285
|
+
end
|
286
|
+
|
287
|
+
@value.should == value
|
288
|
+
end
|
metadata
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: up_the_irons-immutable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.3"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Garry Dolley
|
8
|
+
- Lucas de Castro
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date:
|
13
|
+
date: 2009-05-16 00:00:00 -07:00
|
13
14
|
default_executable:
|
14
15
|
dependencies: []
|
15
16
|
|
16
|
-
description:
|
17
|
+
description: Declare methods as immutable.
|
17
18
|
email: gdolley@ucla.edu
|
18
19
|
executables: []
|
19
20
|
|
@@ -29,6 +30,7 @@ files:
|
|
29
30
|
- COPYING
|
30
31
|
has_rdoc: false
|
31
32
|
homepage: http://github.com/up_the_irons/immutable/tree/master
|
33
|
+
licenses:
|
32
34
|
post_install_message:
|
33
35
|
rdoc_options: []
|
34
36
|
|
@@ -49,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
51
|
requirements: []
|
50
52
|
|
51
53
|
rubyforge_project:
|
52
|
-
rubygems_version: 1.
|
54
|
+
rubygems_version: 1.3.5
|
53
55
|
signing_key:
|
54
56
|
specification_version: 2
|
55
57
|
summary: Declare methods as immutable, somewhat like Java's 'final' keyword but still allowing child classes to override.
|