A clean way to require all files in an application without ruby ​​rudders?

I'm trying to write a game in Ruby (not Rails) as a way to teach it myself better. (Sense, I would like to do it right, but if I try to teach something that just won’t work in Ruby, I will switch languages.) I have a problem with ordering, and I wonder if there is a clean way to do it following.

Here is my structure:

game Gemfile src models character.rb game_object.rb init.rb 

Instead of listing each file separately, init.rb requires these files:

  Dir['./src/**/*.rb'].each do |app| require app end 

game_object.rb is still very simple, but character.rb looks like this:

 module Game class Character < Game::GameObject attr_accessor :name def initialize(name) @name = name end end end 

Unfortunately, if I do this, I get a "uninitialized constant Game :: GameObject (NameError)", unless I explicitly require a game for other files.

It seems to me that I have several options:

  • Load game_object (and other superclasses) into init.rb before the others.
  • Requiring game_object in character.rb, which seems problematic, because depending on which path I use, I understand that it can download the file several times.
  • Download each file separately and manage the order completely manually, so that I have full control.

It all seems more complicated than it should be. Is there a cleaner way?

+4
source share
2 answers

Just putting it: more code doesn't mean dirty, just as often as less code doesn't mean clean.

The requirement that your files manually reduce the headache in the long run - it solves the problems of the download order and prevents you from requiring files that you really don't want. In addition, anyone who watches your code later has a nice, clean manifest of what is loaded into your application.

My suggestions:

  • Leave the src folder, it is redundant - your Ruby application is the whole source.
  • Map namespaces to folders
  • Use explicit requirements (this becomes easier when using # 2:

Example:

 game/ bin/ gamerunner Gemfile lib/ game.rb game/ game_object.rb models/ character.rb spec/ spec_helper.rb models/ character_spec.rb 

You write specifications / tests, right?

Then in lib/game.rb :

 require 'game/game_object.rb' # require the rest of your library as you build it module Game end 

And in your init:

 require 'game' require 'models/character.rb' 

It’s much cleaner, much easier to extract from the future and solve your problem.

+5
source

I have not done this before, but you can add your own autoload logic to Module#const_missing .

 class Module def const_missing_with_autoload(c) components = [] (self.to_s.split("::") + c.to_s.split("::")).reverse.each do |comp| components.unshift(comp.gsub(/([az])([AZ])/, "\\1_\\2").downcase) begin require File.join(*components) return const_get(c) rescue LoadError end end const_missing_without_autoload(c) end alias_method :const_missing_without_autoload, :const_missing alias_method :const_missing, :const_missing_with_autoload end 

I assumed that this would work without the swizzling method, but I could not get it to work. I would like someone to post a clean solution that achieves what I'm trying to do. FWIW, just adding ActiveSupport to your project would probably be useful anyway.

0
source

Source: https://habr.com/ru/post/1385724/


All Articles