Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix rubocop offense for a class class a::b::c

I have following file lib/a/b/c.rb

class a::b::c
  def request(env)
    #some code here
  end
end

Now i am using rubocop style

Style/ClassAndModuleChildren:
  Enabled: true

I am getting rubocop offense for this

lib/a/b/c.rb:1:7: C: Use nested module/class definitions instead of compact style.
class a::b::c

When i update my code to following offence get fixed

Style 1

class a
  class b
    class c
      def request(env)
        #some code here
      end
    end
  end
end

Style 2

module a
  module b
    class c
      def request(env)
        #some code here
      end
    end
  end
end

I think i should use Style 2 as i am using require 'a' in one of my file.

Please let me know how to fix this type & offences and reason for it

like image 934
Salil Avatar asked Jan 07 '16 07:01

Salil


2 Answers

The reason this is marked as offence is that constants resolution works lexically, rather than semantically in ruby. This is not intuitive and might lead to some obscure errors (for example if you have two classes with the same name in two different scopes). Compare these two cases:

# Given
module Foo
  X = 42
end

# This
module Foo
  class Bar
    def baz
      puts X
    end
  end
end

# VS
class Foo::Bar
  def baz
    puts X
  end
end

Now when you call:

Foo::Bar.new.baz

In the first case you will get 42, in the second - NameError: uninitialized constant Foo::Bar::X


As for which is the correct way to fix it: Note that using the short syntax will give you an error if Foo doesn't already exist. The answer is - you should use whatever Foo is. If it's a class - use class, if it's a module - module.
like image 157
ndnenkov Avatar answered Nov 17 '22 14:11

ndnenkov


Class class is essentially derived from Module class, that’s why Class is a Module with some added functionality; basically the difference is in that Classes might be instantiated.

So, the answer to your question would be: use whatever is more suitable in your case (and by the information given it is impossible to say, what it is.)

require 'a' has nothing to do with the case, since require directive just forces ruby interpreter to load the respective code.

NB: that kind of question is the exact reason why Rubocop complains: it prevents you from using something you are not certain about and forces you to understand, is it in fact Module, or Class by it’s nature.

BTW, since you mentioned you have require 'a' somewhere, it probably means that in this a.rb you have already either module A or class A.

BTW#2 Both class and module names must begin with capital letter, because they are to be constants.

like image 31
Aleksei Matiushkin Avatar answered Nov 17 '22 15:11

Aleksei Matiushkin