# Extending modules defined in a ruby library via C#

**URL:** <https://www.ruby-forum.com/t/extending-modules-defined-in-a-ruby-library-via-c/159114>\
**Category:** IronRuby\
**Created:** [January 31, 2009, 7:42pm UTC](https://www.ruby-forum.com/t/extending-modules-defined-in-a-ruby-library-via-c/159114 "2009-01-31T19:42:16Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![murena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/7ba0ec/32.png) [@murena](https://www.ruby-forum.com/u/murena)\
**Post date:** [January 31, 2009, 7:42pm UTC](https://www.ruby-forum.com/t/extending-modules-defined-in-a-ruby-library-via-c/159114/1 "2009-01-31T19:42:16Z")

</div>

Hi,

I think I’ve stumbled on a bug of IronRuby, but I would like to hear  
your thoughts about this before filing a report on the bug tracker as  
I might be missing something or doing something wrong.

I have a ruby library in which is defined a module and this module  
holds a few classes and constants. Then I wrote a library in C# where  
the same module is defined to add more classes other than the ones  
defined on the ruby side. Now if I load the assembly first and then i  
require my ruby library everything works fine, but if I require the  
ruby library first and then load the assembly, the module defined by  
the ruby lib gets totally wiped off leaving there only what was  
defined in the assembly.

Given that in similar scenarios we obviously can’t use Extends =  
typeof(…) in the RubyModuleAttribute, shouldn’t modules previously  
defined in ruby code be automatically extended instead of being  
erased/redefined (which is definitely broken)? Right below here you  
can find the code to reproduce and verify the reported behaviour (for  
convenience I also made an attachment to this mail).

# =========== foo.rb ===========

def test(a)  
a.each{ |s| puts “#{s} is #{begin eval(s); rescue NameError;  
‘undefined’ end}”}  
end

module Foo  
class Bar; end  
VERSION = 1  
end

/\* ======== Nrk.Foo.Test.cs ======== \*/  
namespace Nrk.Foo.Test {  
[RubyModule]  
public static class Foo {  
[RubyClass]  
public static class Hoge {  
[RubyMethod(“piyo?”, RubyMethodAttributes.PublicSingleton)]  
public static bool Piyo(Object self) {  
return true;  
}  
}  
}  
}

# =========== test\_assembly\_first.rb ===========

load\_assembly ‘Nrk.Foo.Test’, ‘Nrk.Foo.Test’  
require ‘foo.rb’

test [‘Foo’, ‘Foo::Bar’, ‘Foo::VERSION’, ‘Foo::Hoge’, ‘Foo::Hoge.piyo?’]

# =========== test\_ruby\_first.rb ===========

require ‘foo.rb’  
load\_assembly ‘Nrk.Foo.Test’, ‘Nrk.Foo.Test’

test [‘Foo’, ‘Foo::Bar’, ‘Foo::VERSION’, ‘Foo::Hoge’, ‘Foo::Hoge.piyo?’]

# =========== OUTPUT #1 ===========

Foo is Foo  
Foo::Bar is Foo::Bar  
Foo::VERSION is 1  
Foo::Hoge is Foo::Hoge  
Foo::Hoge.piyo? is true

# =========== OUTPUT #2 ===========

Foo is Foo  
Foo::Bar is undefined  
Foo::VERSION is undefined  
Foo::Hoge is Foo::Hoge  
Foo::Hoge.piyo? is true

---

<div class="post-metadata">

**Author:** ![murena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/7ba0ec/32.png) [@murena](https://www.ruby-forum.com/u/murena)\
**Post date:** [February 1, 2009, 1:13am UTC](https://www.ruby-forum.com/t/extending-modules-defined-in-a-ruby-library-via-c/159114/2 "2009-02-01T01:13:03Z")

</div>

.NET types can never be 100% compatible with Ruby classes; the semantics  
are simply too different. What would you expect to happen, for  
instance, if you were to say the following:

module System::IDisposable; end  
class System::Collections::ArrayList; include System::IDisposable; end;  
x = System::Collections::ArrayList.new  
require ‘mscorlib’

Clearly, the “real” System::Collections::ArrayList can’t implement  
IDisposable because the type is immutable. And the type we created to  
represent the variable x can’t be a “real” ArrayList because we didn’t  
know about that class when x was allocated.

So this leaves us with two possibilities:

1. Always overwrite the previously defined constants with the newly  
imported CLR types
2. Fail to load the redefined types

…and we’re currently doing the first. While it seems reasonable to  
fail, it raises questions about what to do if 40 types can be loaded  
successfully but one can’t be. Do we raise an exception even though  
there were 40 successes? Or do we fail to load any types at all?

Monkey-patching CLR types is never going to be able to work identically  
to monkey-patching pure Ruby types.

---

<div class="post-metadata">

**Author:** ![murena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/7ba0ec/32.png) [@murena](https://www.ruby-forum.com/u/murena)\
**Post date:** [February 1, 2009, 7:58am UTC](https://www.ruby-forum.com/t/extending-modules-defined-in-a-ruby-library-via-c/159114/3 "2009-02-01T07:58:55Z")

</div>

That’s absolutely true for arbitrary CLR types. Library types (those  
marked by RubyClass attribute) are handled differently though. They can  
be seen like collections of extension methods. So it makes sense to  
extend a Ruby class using library methods. So far we were focused on  
extending CLR types using library types. Extending Ruby classes could be  
seen as a feature that is not implemented yet. Could you file a feature  
request (bug) on RubyForge?

A possible workaround for you: define a C# method that takes a Ruby  
class and extends it in manually using methods on RubyModule/RubyClass  
(AddMethod etc.). You would call this helper after loading the assembly.

Tomas

---

<div class="post-metadata">

**Author:** ![murena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/7ba0ec/32.png) [@murena](https://www.ruby-forum.com/u/murena)\
**Post date:** [February 1, 2009, 10:59am UTC](https://www.ruby-forum.com/t/extending-modules-defined-in-a-ruby-library-via-c/159114/4 "2009-02-01T10:59:08Z")

</div>

On Sun, Feb 1, 2009 at 07:30, Tomas M.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> That’s absolutely true for arbitrary CLR types. Library types  
> (those marked by RubyClass attribute) are handled differently  
> though. They can be seen like collections of extension methods.  
> So it makes sense to extend a Ruby class using library methods.

In fact, I think the described behaviour is perfectly fine for CLR  
types and I was sort of expecting this, but not for those types marked  
by RubyClass.

> So far we were focused on extending CLR types using library  
> types. Extending Ruby classes could be seen as a feature that  
> is not implemented yet. Could you file a feature request (bug) on  
> RubyForge?

OK, I will file it later. Maybe I will assign a lower priority to this  
as I guess it is not really a common scenario and I don’t know how  
many folks are trying to build extension libs for IronRuby. But still,  
IMHO it would be nice to get this fixed before going 1.0.

> A possible workaround for you: define a C# method that takes  
> a Ruby class and extends it in manually using methods on  
> RubyModule/RubyClass (AddMethod etc.). You would call this  
> helper after loading the assembly.

Yeah I was thinking about something along that way, I was just waiting  
for confirmations before going on.

FYI I got into this particular case while porting Florian F.'s json  
library (see [http://json.rubyforge.org/](http://json.rubyforge.org/)) which provides two variants  
for the core bits, namely “extension” (implemented in C) or “pure”  
(ruby). Both relies on a few methods, classes and constants previously  
defined in the same module in which they are loaded (JSON). When  
loading the JSON::Ext::Parser, I was getting everything in JSON and  
JSON::Ext erased.

require ‘json/common’

module JSON  
module Ext  
# require ‘json/ext/parser’  
# require ‘json/ext/generator’

```
load_assembly 'IronRuby.Libraries.Json', 'IronRuby.Libraries.Json'

$DEBUG and warn "Using c extension for JSON."
JSON.parser = Parser
JSON.generator = Generator

```

end  
end

I could also define the Parser and Generator classes into a different  
global module and then assign them (e.g. JSON.parser =  
IronJson::Ext::Parser), but well there is no fun doing this 🙂

–  
Daniele A.  
[http://www.clorophilla.net/blog/](http://www.clorophilla.net/blog/)
