Reputation: 16242
When you want to namespace a bunch of classes in ruby, you typically do:
# my_namespace.rb
module MyNamespace
class ClassOne
# ...
end
class ClassTwo
# ...
end
# ...
end
which has the unfortunate side effect of increasing the indent level of all the code in the file. I'd much rather be able do something like issue a directive at the top of the file which effectively said, "everything in this file should be in the MyNamespace
module".
Is this possible?
NOTE: I'm aware I could just keep the module
wrapping but not indent everything, but that solution is unacceptable imo.
Upvotes: 0
Views: 254
Reputation: 7396
I consider the ability to express the notion of "everything in this file should be in some module" very useful for Ruby expressiveness and therefore find author's question perfectly valid.
The same concept is implemented in C# under the name of "File scoped namespace declarations" and looks as follows:
namespace SampleFileScopedNamespace;
class SampleClass { }
Unfortunately, the only way to use namespaces without indentation in Ruby at this moment is to use scope resolution operator, that is ::
:
class MyNamespace::ClassOne
end
But besides eliminating indentation, scope resolution operator works a bit differently than the module
keyword. In particular it:
Requires constants to be initialized before use or you will get the NameError
exception. In the example above MyNamespace
must exist before declaring ClassOne
.
Affects the way the constant lookup works, which may be surprising in some cases. The official Ruby community guide recommends avoiding it altogether.
Surprisingly, there was no such feature request in Ruby bug tracker so I created a new ticket.
P.S. I am posting this clarification as an answer in order to bring attention to the importance of the problem and also because long formatted messages are not particular readable in the comments section.
Upvotes: 1
Reputation: 11343
The indentation level of the code is a function of an editor/ide. The simple answer is: Don't indent the code.
It is only a visual aspect, the level of scope is increased, regardless of the visual effect.
This can be avoided through taking advantage of different syntax, like using the scope operator as Sergio Tulentsev mentioned.
You could use eval and read in a file, but I think that would be terrible, though it would fix the indentation "problem".
module General
module_eval "class One end"
module_eval "class Two; p 'Done creating Two'; def self.report(); 'I am in General::Two' ; end; end"
module_eval File.read('three.rb')
end
p General::Two.report
p General::Three.new.report
As a separate file, three.rb
class Three
def report
"This is #{self.class} and has #{self.class.ancestors}"
end
end
But apparently nothing really reasonable for keeping the indentations away.
I do find it as a helpful tool visually to track scope when reading, based on indentation, so having 2, 4. 6 spaces or 8 spaces as indentation really doesn't seem like much of a pain. Having 8 spaces (tab representation) at each level would be a lot more irritating as things flow off to the right of the screen.
Upvotes: 0
Reputation: 1995
Rubocop will tell you what to do according to the Ruby style guide!
Edit:
# my_namespace.rb
module MyNamespace
class ClassOne
# ...
end
class ClassTwo
# ...
end
# ...
end
Causes this Rubocop warning:
Warning:13:1: C: Incorrect indentation detected (column 0 instead of 2).
Upvotes: -3