Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preference of code style in module nesting

Tags:

ruby

I got bit by assuming that

module A
  module B
  end
end

and

module A::B
end

are alike. I was able to find a solution from this blog, this SO thread and and this SO thread.

Why and when should one prefer the compact syntax A::B over the other, given that it evidently has a drawback? I have a intuition that it could be related to performance, as looking up constants in more namespaces requires more computation. But I was not able to verify this by benchmarking normal classes.

like image 942
rahulmishra Avatar asked Feb 23 '18 05:02

rahulmishra


2 Answers

These two methods of writing get confused quite often.

First is to say, that to my best knowledge there is no measurable performance difference. (one constant look-up in the below written example)

The most obvious difference, probably the most known, is that your second example (module A::B) requires for the module A to exist in the time of the definition.

Otherwise than than that most people think they are interchangeable. That is not true.

Modules are simply constants in ruby and so regular constant look-up applies.

Let me show it on an example:

module A
  class Test
  end

  module B
    class Show
      p Module.nesting # =>[A::B::Show, A::B, A]

      def show_action
        Test.respond_with(%q(I'm here!))
      end
    end
  end
end

On the other hand if you call it via the A::B look what happens:

module A
  class Test
  end
end

module A::B
  class Show
    p Module.nesting # => [A::B::Show, A::B]

    def show_action
      Test.respond_with(%q(I'm here!))
    end
  end
end

The difference is that .nesting produces:

1) in the first case: [A::B::Show, A::B, A] (you are nested in module A)

2) in the second case: [A::B::Show, A::B] (here not)

like image 190
tukan Avatar answered Nov 09 '22 16:11

tukan


The first one has more information than the second one. Naturally, in most cases, you can assume that the second form can always be replaced by the first one, but not the other way around. In fact, you cannot use the second form unless A is defined in advance. But be careful that the return values of Module#nesting differ between the two forms as the method has lexical scope interpretation.

like image 30
sawa Avatar answered Nov 09 '22 15:11

sawa