Чистый способ требовать все файлы в не-Rails Ruby приложении? - PullRequest
4 голосов
/ 11 декабря 2011

Я пытаюсь написать игру на Ruby (не Rails), чтобы научить ее лучше.(Это означает, что я хотел бы сделать это правильно, но если я пытаюсь запихнуть что-то, что просто не работает в Ruby, я переключу языки.) У меня возникает проблема с требованием заказа, и яМне интересно, есть ли чистый способ сделать следующее.

Вот моя структура до сих пор:

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

Вместо того, чтобы перечислять каждый файл по отдельности, для init.rb требуются такие файлы:

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

game_object.rb пока что очень прост, но character.rb выглядит так:

module Game
  class Character < Game::GameObject
    attr_accessor :name

    def initialize(name)
      @name = name
      end
  end
end

К сожалению, если я это сделаю, я получу "неинициализированную константу Game:: GameObject (NameError) ", если я явно не требую game_object перед другими файлами.

Мне кажется, у меня есть несколько вариантов здесь:

  1. Загрузить game_object (и другие суперклассы)в init.rb раньше других.
  2. Требуется game_object в character.rb, что кажется проблематичным, поскольку в зависимости от того, какой путь я использую, я понимаю, что он может загружать файл несколько раз.
  3. Загрузитькаждый файл в отдельностии управлять заказом полностью вручную, чтобы у меня был полный контроль.

Все это кажется более сложным, чем должно быть.Есть ли более чистый способ?

Ответы [ 2 ]

5 голосов
/ 11 декабря 2011

Просто выкладываем это: больше кода не означает «грязный», так же, как часто меньше кода не означает «чистый».

Ручной запрос файлов даст вам меньше головной боли в долгосрочной перспективе- он решает проблемы с порядком загрузки и не позволяет запрашивать файлы, которые вам на самом деле не нужны.Кроме того, любой, кто смотрит на ваш код позже, имеет хороший, чистый манифест того, что загружается в ваше приложение.

Мои предложения:

  1. Удалите папку src, это избыточно- ваше Ruby-приложение all source.
  2. Сопоставление ваших пространств имен с папками
  3. Используйте явные требования (это становится проще, когда вы используете # 2:

Пример:

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

Вы пишете спецификации / тесты, не так ли?

Затем в lib/game.rb:

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

module Game
end

И вВаша инициация:

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

Гораздо чище, гораздо проще извлечь из нее позже и должна решить вашу проблему.

0 голосов
/ 11 декабря 2011

Я не делал этого раньше, но вы могли бы добавить свою собственную логику автозагрузки к 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(/([a-z])([A-Z])/, "\\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

Я предполагал, что это будет работать без метода swizzling, но я не мог этого добитьсяза работой.Я хотел бы, чтобы кто-нибудь опубликовал чистое решение, которое достигает того, что я пытаюсь сделать.FWIW, просто добавление ActiveSupport в ваш проект, вероятно, было бы полезно в любом случае.

...