【问题标题】:Forcing rails to autoload class强制rails自动加载类
【发布时间】:2012-04-07 19:50:42
【问题描述】:

我在 /app/models 的单个文件中有几个小类,类似于:

# /app/models/little_class.rb
class LittleClass; ...do stuff; end;
class AnotherLittleClass; ...do stuff; end;

Rails 似乎只适合在反映类名的文件中自动加载类。因此,在文件之外引用 AnotherLittleClass 会引发“未初始化常量”错误,如下所示,直到引用 LittleClass:

irb(main):001:0> AnotherLittleClass 
NameError: uninitialized constant AnotherLittleClass
irb(main):02:0> LittleClass
=> LittleClass
irb(main):03:0> AnotherLittleClass
=> LittleClass2

将它们拆分为单独的文件会很痛苦和混乱。有没有办法自动加载这些类,所以在没有 LittleClass 的情况下引用 AnotherLittleClass 不会引发错误?

【问题讨论】:

    标签: ruby-on-rails ruby autoload


    【解决方案1】:

    您可以将它们放入一个模块中并在此命名空间SomeLittleClasses::LittleClass.do_something中使用它们

    # /app/models/some_little_classes.rb
    module SomeLittleClasses
    
      class LittleClass
        def self.do_something
          "Hello World!"
        end
      end
    
      class AnotherLittleClass
        def self.do_something
          "Hello World!"
        end
      end
    
    end
    

    【讨论】:

      【解决方案2】:

      试试这个技巧:

      1.9.2p312 :001 > AnotherLittleClass.new
      # => NameError: uninitialized constant AnotherLittleClass
      1.9.2p312 :002 > autoload :AnotherLittleClass, File.dirname(__FILE__) + "/app/models/little_class.rb"
      # => nil 
      1.9.2p312 :003 > AnotherLittleClass.new
      # => #<AnotherLittleClass:0xa687d24> 
      

      【讨论】:

      • 嗯,明白了。可惜我必须手动指定所有类。谢谢@WarHog
      • 但是,如果你关心的话,这个技巧会破坏 Rails 对类的重新加载。因此,如果您要对这些类进行任何更改,则必须重新启动应用程序。
      【解决方案3】:

      在我看来,这些是你的选择:

      1. 将您的文件拆分为每个类一个文件,将它们放在根据 rails 约定命名的目录 (SomeClass => some_class.rb) 和启动文件中(例如,在 config/initializers 中创建一个文件) ,调用:

        autoload_paths Rails.application.config.root + "/path/to/lib"
        
      2. 在启动文件中添加这样的内容:

        %W[
            Class1 Class2
            Class3 Class4 Class4
        ].map(&:to_sym).each dp |klass|
            autoload klass,Rails.application.config.root + "/path/to/lib/file"
        end
        

        这当然必须在每次向文件中添加新类时更新。

      3. 将所有类移动到模块/类命名空间中并调用autoload 将其添加

      4. 只需在带有require 的启动文件中预先加载整个文件。问问自己:额外的努力是否需要延迟加载此文件?

      【讨论】:

        【解决方案4】:

        给出以下文件app/models/statistic.rb

        class Statistic
          # some model code here
        end
        
        class UsersStatistic < Statistic; end
        class CommentsStatistic < Statistic; end
        class ConnectionsStatistic < Statistic; end
        

        创建文件config/initializers/autoload_classes.rb并添加以下代码:

        # Autoloading subclasses that are in the same file
        
        
        # This is the normal way to load single classes
        #
        # autoload :UsersStatistic, 'statistic'
        # autoload :CommentsStatistic, 'statistic'
        # autoload :ConnectionsStatistic, 'statistic'
        
        
        # This is the most dynamic way for production and development environment.
        Statistic.subclasses.each do |klass|
          autoload klass.to_s.to_sym, 'statistic'
        end
        
        
        
        # This does the same but loads all subclasses automatically. 
        # Useful only in production environment because every file-change 
        # needs a restart of the rails server.
        # 
        # Statistic.subclasses
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-10
          • 1970-01-01
          • 1970-01-01
          • 2020-02-24
          • 2020-03-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多