Search code examples
rubylibgosu

ruby catch classes as they are defined


Building tile games or simulations in Ruby Gosu always makes me end upp with a list of all available tiles, saved by their class. For example [Pipe, PipeJunktion, Box, Pump] and so on. Each class is defined in one of a few separate files, which i required from the main program. For now i have to add the class myself to this list every time I add a new tile to the game. I was wondering if there was a way to catch all loading classes from a file.

Something along the lines of:

allTiles = []
require_relative 'tiles.rb'.each_class {|class| allTiles << class}

would be handy. Or can this be solved with modules in some way?


Solution

  • Checking which classes were added by a file is not something that's easily or commonly done. A better approach would be to put all the tile classes under a single namespace. Since classes can be re-opened, these can be split among multiple files.

    class Tiles
      class Pipe
        # ...
      end
    end
    
    class Tiles
      class Box
        # ...
      end
    end
    

    Then Tiles.constants could would return an array of symbols: [:Pipe, :Box], and could be used to get a list of class references using Tiles.constants.map { |const| Tiles.const_get const } or Tiles.constants.map &Tiles.method(:const_get)

    If for whatever reason it was really important to know which constants were added by a specific file, the following code shows an approach:

    constants1 = Object.constants
    require "./tiles.rb"
    constants2 = Object.constants
    added_constants = constants2 - constants1
    

    If tiles.rb had class definitions for Pipe and Box, then added_constants would be [:Pipe, :Box].

    The problem with this approach is that might show constants added by gems, for example:

    constants1 = Object.constants
    require 'mechanize'
    class Foo
    end
    constants2 = Object.constants
    added_constants = constants2 - constants1
    

    Since I called require 'mechanize', the added_constants list will be quite long and include much more than just Foo.