Skip to content

Commit

Permalink
Fix inheritance logic
Browse files Browse the repository at this point in the history
  • Loading branch information
lsegal committed Apr 1, 2010
1 parent b05891a commit 7a04d32
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
12 changes: 9 additions & 3 deletions lib/export.rb
Expand Up @@ -6,19 +6,25 @@ def export_list
end

def export(meth, *classes)
meth = meth.to_s
meth, expmeth = meth.to_s, "__exported__#{meth}"
(export_list[meth] ||= []).push(*classes)
alias_method "__exported__#{meth}", meth
alias_method expmeth, meth
private expmeth
public meth
define_method(meth) do |*args, &block|
cclass, classes = caller_class, self.class.export_list[meth]
if classes && !classes.any? {|k| cclass >= k }
if cclass == false
raise NoMethodError, "`#{meth}' is not accessible outside #{self.class}"
elsif cclass != self.class && classes && !classes.any? {|k| cclass <= k }
raise NoMethodError,
"`#{meth}' is not accessible to #{cclass.inspect}:#{cclass.class.inspect}",
caller
end
send("__exported__#{meth}", *args, &block)
end
end

alias friend export
end

(RUBY_VERSION >= "1.9.1" ? BasicObject : Object).send(:extend, Export)
12 changes: 11 additions & 1 deletion test/export_test.rb
Expand Up @@ -4,8 +4,10 @@
class A; def bar; D.new.foo end end
class B; def bar; D.new.foo end end
class C; def bar; D.new.foo end end
class E < B; def bar; D.new.foo end end
class D
def foo; "foobar" end
def foo; "foobar" end
def bar; foo end
export :foo, A, B
end

Expand All @@ -21,4 +23,12 @@ def test_export_B
def test_export_C
assert_raises(NoMethodError) { C.new.bar }
end

def test_export_E
assert_equal "foobar", E.new.bar
end

def test_local_call
assert_equal "foobar", D.new.bar
end
end

0 comments on commit 7a04d32

Please sign in to comment.