Martinicity: Ruby Namespace Conflicts Mike Blake tag:www.martinicity.net,2005:Typo Typo 2008-04-05T01:44:03+00:00 Mike Blake urn:uuid:1adb0c92-2859-42ba-822a-1ef44bf0ad03 2006-07-15T10:30:00+00:00 2008-04-05T01:44:03+00:00 Ruby Namespace Conflicts <p><b>Declare new Classes Inside Modules to Avoid Conflicts</b></p> <p>In the ruby language you cannot have a Module with the same name as a Class. The reason is that in any instance of the ruby interpreter, all root level accessible Objects are stored in a Hash of constants as either Modules or Classes. This can get cluttered pretty quickly in a large application. Try throwing the line <code>'p Module.constants'</code> in the middle of a medium sized Rails application.</p> <p>However, if a class is part of a Module, which acts as a namespace in ruby, it&#8217;s name never makes it to Module.constants. So it can have the same name as an existing Module.</p> To see a demonstration of this, I executed the following ruby code. <div class="typocode"><pre><code class="typocode_ruby "><span class="keyword">module </span><span class="module">One</span> <span class="keyword">end</span> <span class="keyword">class </span><span class="class">Two</span> <span class="keyword">def </span><span class="method">self.to_s</span> <span class="punct">&quot;</span><span class="string">2</span><span class="punct">&quot;</span> <span class="keyword">end</span> <span class="keyword">end</span> <span class="ident">p</span> <span class="constant">Two</span> <span class="keyword">class </span><span class="class">One::Two</span> <span class="keyword">def </span><span class="method">self.to_s</span> <span class="punct">&quot;</span><span class="string">1::2</span><span class="punct">&quot;</span> <span class="keyword">end</span> <span class="keyword">end</span> <span class="ident">p</span> <span class="constant">One</span><span class="punct">::</span><span class="constant">Two</span> <span class="keyword">class </span><span class="class">One::Three</span> <span class="keyword">def </span><span class="method">self.to_s</span> <span class="punct">&quot;</span><span class="string">1::3</span><span class="punct">&quot;</span> <span class="keyword">end</span> <span class="keyword">end</span> <span class="ident">p</span> <span class="constant">One</span><span class="punct">::</span><span class="constant">Three</span> <span class="ident">p</span> <span class="constant">Module</span><span class="punct">.</span><span class="ident">constants</span> <span class="keyword">class </span><span class="class">One::One</span> <span class="keyword">def </span><span class="method">self.to_s</span> <span class="punct">&quot;</span><span class="string">1::1</span><span class="punct">&quot;</span> <span class="keyword">end</span> <span class="keyword">end</span> <span class="ident">p</span> <span class="constant">One</span><span class="punct">::</span><span class="constant">One</span> <span class="keyword">class </span><span class="class">One</span> <span class="keyword">def </span><span class="method">self.to_s</span> <span class="punct">&quot;</span><span class="string">1</span><span class="punct">&quot;</span> <span class="keyword">end</span> <span class="keyword">end</span> <span class="ident">p</span> <span class="constant">One</span> </code></pre></div> <p>Here&#8217;s what happened. (output below). A Module named <strong>One</strong> was created and so was a class named <strong>Two</strong>. And the interpreter saw that it was good. Then, in the <strong>One</strong> module, classes <strong>One</strong>, <strong>Two</strong>, and <strong>Three</strong> were created. And the interpreter saw that it was good.</p> <p>Then I took a peek at <strong>Module.constants</strong>. The <strong>One</strong> Module, and the <strong>Two</strong> Class were saved as constants. But the <strong>Three</strong> Class was not stored as a constant because it is not at the root level. Since Classes created within Modules are not stored as constants,I was allowed to create a <strong>One</strong> Class inside the <strong>One</strong> Module without a getting a TypeError.</p> <p>But all is not well in paradise. When the program tried to create a class named One it got the error</p> <font color='red'>-:35: One is not a class (TypeError)</font> <p>That&#8217;s because it&#8217;s already stored in constants as a Module.</p> <p>As Ruby grows in popularity, this could become a problem. Especially in the Rails framework where all Model objects are at the root level. Considering this, it&#8217;s a good habit to <b>use modules as namespaces when creating new classes</b> in things like plugins and gems to avoid a TypeError.</p> <p><br></p> <p><b>Output:</b></p> <p> <p><br></p> <p>1::2</p> <p>1::3</p> <p>2</p> <code>["TrueClass", "FloatDomainError", "Fixnum", "TOPLEVEL\_BINDING", "SignalException", "String", "SystemCallError", "UnboundMethod", "Buffering", "Rational", "ThreadGroup", "CROSS\_COMPILING", "ScriptError", "MatchData", "Thread", "IndexError", "STDOUT", &lt;font color='red'&gt;"One"&lt;/font&gt;, "SecurityError", "Integer", "SingleForwardable", "Config", "RELEASE\_DATE", "Exception", "NoMethodError", "Proc", "GC", "TypeError", "Binding", "Signal", "FALSE", "RUBY\_PLATFORM", "Forwardable", "Bignum", "SystemExit", "Date", "NotImplementedError", "EOFError", "FileTest", "TRUE", "Numeric", "Interrupt", "ARGF", "Array", "SyntaxError", "MatchingData", "RUBY_VERSION", "ParseDate", "Time", "RangeError", "ENV", "NIL", "Enumerable", "Module", "PLATFORM", "STDERR",&lt;font color='red'&gt;"Two"&lt;/font&gt;, "NoMemoryError", "Float", "Regexp", "DateTime", "Data", "ZeroDivisionError", "ARGV", "Dir", "Process", "Range", "ThreadError", "ArgumentError", "Object", "IO", "Comparable", "LocalJumpError", "Math", "Marshal", "RuntimeError", "STDIN", "Method", "VERSION", "RegexpError", "Hash", "Precision", "Kernel", "Continuation", "File", "SystemStackError", "OpenSSL", "FalseClass", "Errno", "NilClass", "StandardError", "LoadError", "ObjectSpace", "RUBY\_RELEASE\_DATE", "Gem", "IOError", "Symbol", "Struct", "NameError", "Class"] 1::1 &lt;font color='red'&gt;-:35: One is not a class (TypeError)&lt;/font&gt; AlexW urn:uuid:24695331-dc79-4017-bb66-b5ed3b36c416 2006-12-18T23:15:20+00:00 2006-12-18T23:15:20+00:00 Comment on Ruby Namespace Conflicts by AlexW <p>Great article! I've also run into this problem but had no idea what was causing it!</p> <p>Thanks!</p>