在rails3中默认不在加载lib目录下的rb文件。

config/application.rb文件中

1
2
#Custom directories with classes and modules you want to be autoloadable.
#config.autoload_paths += %W(#{config.root}/exters)

显然被注释掉了。

要开启则取消注释,修改为自己想加载的路径。

1
config.autoload_paths += %W(#{config.root}/lib)

这样rails会自动加载lib下的rb文件。


  • 没有子目录

    在lib下有go.rb

    1
    2
    3
    4
    5
    
    module Go
        def say
            puts 'hello'
        end
    end

    在其他地方使用的时候include进来,例如

    1
    2
    3
    4
    5
    6
    
    class ProductsController < ApplicationController
        include Go
        def index
            say()
        end
    end
  • 含有子目录

    在lib下有tools目录,下面有go.rb

    1
    2
    3
    4
    5
    
    module Go
        def say
            puts 'hello'
        end
    end

    controller中

    1
    2
    3
    4
    5
    6
    
    class ProductsController < ApplicationController
        include Go
        def index
            say()
        end
    end

    很遗憾这这样会抛出异常uninitialized constant

    原因rails加载lib使用的const_missing机制,在找不到常量时,会根据这个常量的名字,加载文件。 >如果类名(常量名、模块名都是常量)是 A::B::C,那么就把 :: 替换为 ‘/‘,单词变成小写,然后尝试在 ActiveSupport::Dependencies.autoload_paths 里的路径中,去查找是否有 a/b/c.rb。

    显然lib下没有任何rb可加载,inculde Go肯定是找不到的,此时触发const_missing还是找不到。

    应该将go.rb里modules的名字改为Tools::Go

    1
    2
    3
    4
    5
    
    module Tools::Go
        def say
            puts 'hello'
        end
    end

    controller中inlude修改为include Tools::Go

    1
    2
    3
    4
    5
    6
    
    class ProductsController < ApplicationController
        include Tools::Go
        def index
            say()
        end
    end

    同样inculde Tools::Go肯定是找不到的,此时触发const_missing,根据规则可知此时会去加载tools/go.rb,显然加载成功。