Jonah
Jonah

Reputation: 16242

Namespace the contents of a file, but without increasing indent

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

Answers (3)

Artur INTECH
Artur INTECH

Reputation: 7396

February 2025 update:

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

vgoff
vgoff

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

maasha
maasha

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

Related Questions