Julian Honma Julian Honma - 1 month ago 16
Ruby Question

Make a inherited function dynamic

I have a Ruby project that has the following architecture:

Project architecture

All of my child controllers (city1, city2) inherit from the parent controller at the project root. I have a method in the parent controller:

class Controller
def get_directories
Dir.chdir(File.dirname(__FILE__) + "/")
Dir.glob('*').select { |f| File.directory? f }
end
end


My child controllers:

require_relative '../controller'

class City1Controller < Controller
end


and

require_relative '../controller'

class City2Controller < Controller
end


From my understanding, this method looks at the current Working Directory and returns an array of the folders that are inside that directory.

I expected the child controllers to inherit of this function in a way where the get_directories will be local to the child directory, but it's showing the folders in the parent directory.

That's what's happening:

controller.get_directories => city1 city2
city1_controller.get_directories => city1 city2
city2_controller.get_directories => city1 city2


That's what I want to happen:

controller.get_directories => city1 city2
city1_controller.get_directories => monument1 monument2
city2_controller.get_directories => monument3 monument4


If I repeat the exact same method in each child controller (thus overriding the parent definition), it works the way I want to. But isn't that what inheritance supposed to spare us?

Is the issue in the method itself, in how the inheritance works, or how I use it?

Answer

As Sergio already pointed out: __FILE__ is not a method. It is a reference to the current file's name, it returns a relative path to exactly that file in which it is located.

One option might be to pass __FILE__ to the method like this:

class Controller
  def get_directories(file = __FILE__)
    Dir.chdir(File.dirname(file) + "/")
    Dir.glob('*').select { |f| File.directory? f }
  end
end

And the child controllers:

require_relative '../controller'

class City1Controller < Controller
  def get_directories
    super(__FILE__)
  end
end

And

require_relative '../controller'

class City2Controller < Controller
  def get_directories
    super(__FILE__)
  end
end
Comments