Skip to content

Instantly share code, notes, and snippets.

@maxim
Last active January 9, 2025 00:59

Revisions

  1. maxim revised this gist Oct 26, 2013. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    # In Rails 3

    **NOTE**: This post now lives (and kept up to date) on my blog: http://hakunin.com/rails3-load-paths

    ### If you add a dir directly under app/

    Do nothing. All files in this dir are eager loaded in production and lazy loaded in development by default.
  2. maxim revised this gist Sep 10, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@ In either case, everything will be eager loaded in production.

    #### Option 1

    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just `require` it in your rake task. If you need this library to always be loaded for your rails app, you `require` it in an initializer. If you need this library for some of your models or controllers, you `require_dependency` it in those files, and since everything under your `app/` dir is already auto- and eager- loaded as needed, your library will only be "pulled-in" if something that requires it from `app/` or rake, or your custom script, actually gets loaded. See below for why you need to use `require_dependency`.
    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just `require` it in your rake task. If you need this library to always be loaded for your rails app, you `require` it in an initializer. If you need this library for some of your models or controllers, you `require_dependency` (see below why) it in those files, and since everything under your `app/` dir is already auto- and eager- loaded as needed, your library will only be "pulled-in" if something that requires it from `app/` or rake, or your custom script, actually gets loaded.

    #### Option 2 (bad)

  3. maxim revised this gist Sep 10, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@ In either case, everything will be eager loaded in production.

    #### Option 1

    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just `require` it in your rake task. If you need this library to always be loaded for your rails app, you `require_dependency` it in an initializer. If you need this library for some of your models or controllers, you `require_dependency` it in those files, and since everything under your `app/` dir is already auto- and eager- loaded as needed, your library will only be "pulled-in" if something that requires it from `app/` or rake, or your custom script, actually gets loaded. See below for why you need to use `require_dependency`.
    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just `require` it in your rake task. If you need this library to always be loaded for your rails app, you `require` it in an initializer. If you need this library for some of your models or controllers, you `require_dependency` it in those files, and since everything under your `app/` dir is already auto- and eager- loaded as needed, your library will only be "pulled-in" if something that requires it from `app/` or rake, or your custom script, actually gets loaded. See below for why you need to use `require_dependency`.

    #### Option 2 (bad)

    @@ -51,7 +51,7 @@ Regardless of which option you pick (option 1, hint hint), in your lib/ dir you

    #### Why use require_dependency (auto-reloading)

    If you use `require_dependency`, you are enabling auto-reload of your files in development across requests. `require` alone won't do it. I suggested to use it in your rails app, but not in rake tasks, because we don't need to reload classes in rake tasks.
    If you use `require_dependency`, you are enabling auto-reload of your files in development across requests. `require` alone won't do it. I suggested to use it in your rails app, but not in initializers or rake tasks because rake tasks only run once, and changing initializers always requires restart.

    However, it won't work without one additional piece of configuration. In application.rb you should add this:

  4. maxim revised this gist Sep 10, 2013. 1 changed file with 12 additions and 2 deletions.
    14 changes: 12 additions & 2 deletions rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@ In either case, everything will be eager loaded in production.

    #### Option 1

    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just `require` it in your rake task. If you need this library to always be loaded for your rails app, you `require` it in an initializer. If you need this library for some of your models or controllers, you `require` it in those files, and since everything under your `app/` dir is already auto- and eager- loaded as needed, your library will only be "pulled-in" if something that requires it from `app/` or rake, or your custom script, actually gets loaded.
    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just `require` it in your rake task. If you need this library to always be loaded for your rails app, you `require_dependency` it in an initializer. If you need this library for some of your models or controllers, you `require_dependency` it in those files, and since everything under your `app/` dir is already auto- and eager- loaded as needed, your library will only be "pulled-in" if something that requires it from `app/` or rake, or your custom script, actually gets loaded. See below for why you need to use `require_dependency`.

    #### Option 2 (bad)

    @@ -47,4 +47,14 @@ If you add lib/ into `eager_load_paths`, everything will work great. Your files

    #### Organizing lib

    Regardless of which option you pick (option 1, hint hint), in your lib/ dir you should structure your code as if you structure a gem. If you need more than 1 file, you could for example add a same-named directory where everything is properly namespaced, and let your 1 file relatively require files in that directory.
    Regardless of which option you pick (option 1, hint hint), in your lib/ dir you should structure your code as if you structure a gem. If you need more than 1 file, you could for example add a same-named directory where everything is properly namespaced, and let your 1 file relatively require files in that directory.

    #### Why use require_dependency (auto-reloading)

    If you use `require_dependency`, you are enabling auto-reload of your files in development across requests. `require` alone won't do it. I suggested to use it in your rails app, but not in rake tasks, because we don't need to reload classes in rake tasks.

    However, it won't work without one additional piece of configuration. In application.rb you should add this:

    ```
    config.watchable_dirs['lib'] = [:rb]
    ```
  5. maxim revised this gist Sep 10, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ If you put something in the lib/ dir, what you are saying is: "I wrote this libr

    #### Option 2 (bad)

    Another option is to add your whole lib dir into `autoload_paths`: `config.autoload_paths += %W( #{config.root}/lib )`. This means you shouldn't explicitly require your lib anywhere. As soon as you hit the namespace of your dir in other classes, rails will require it. The problem with this is that in Rails 3 autoload paths are not eager loaded in production. And in ruby 1.9 autoload is not threadsafe. You probably want eager loading in production. Requiring your lib explicitly, like in option 1, is akin to eager loading it, which is threadsafe.
    Another option is to add your whole lib dir into `autoload_paths`: `config.autoload_paths += %W( #{config.root}/lib )`. This means you shouldn't explicitly require your lib anywhere. As soon as you hit the namespace of your dir in other classes, rails will require it. The problem with this is that in Rails 3 if you just add something to your autoload paths it won't get eager loaded in production. You would need to add it to `eager_load_paths` instead, which causes a different problem (see below). And in ruby 1.9 autoload is not threadsafe. You probably want eager loading in production. Requiring your lib explicitly, like in option 1, is akin to eager loading it, which is threadsafe.

    #### Option 3 (meh)

  6. maxim revised this gist Sep 10, 2013. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,7 @@ Ask: do I want to namespace modules and classes inside my new dir?
    For example in app/models/products/ you would need to wrap your class in `module Products`.

    If the answer is yes, do nothing. It will just work.

    If the answer is no, add `config.autoload_paths += %W( #{config.root}/app/models/products )` to your application.rb.

    In either case, everything will be eager loaded in production.
  7. maxim revised this gist Sep 10, 2013. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -14,6 +14,8 @@ For example in app/models/products/ you would need to wrap your class in `module
    If the answer is yes, do nothing. It will just work.
    If the answer is no, add `config.autoload_paths += %W( #{config.root}/app/models/products )` to your application.rb.

    In either case, everything will be eager loaded in production.

    ### If you add code in your lib/ directory


  8. maxim revised this gist Sep 10, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -44,4 +44,4 @@ If you add lib/ into `eager_load_paths`, everything will work great. Your files

    #### Organizing lib

    In your lib/ dir you should structure your code as if you structure a gem. If you need more than 1 file, you could for example add a same-named directory where everything is properly namespaced, and let your 1 file relatively require files in that directory.
    Regardless of which option you pick (option 1, hint hint), in your lib/ dir you should structure your code as if you structure a gem. If you need more than 1 file, you could for example add a same-named directory where everything is properly namespaced, and let your 1 file relatively require files in that directory.
  9. maxim revised this gist Sep 10, 2013. 1 changed file with 17 additions and 0 deletions.
    17 changes: 17 additions & 0 deletions rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -25,6 +25,23 @@ If you put something in the lib/ dir, what you are saying is: "I wrote this libr

    Another option is to add your whole lib dir into `autoload_paths`: `config.autoload_paths += %W( #{config.root}/lib )`. This means you shouldn't explicitly require your lib anywhere. As soon as you hit the namespace of your dir in other classes, rails will require it. The problem with this is that in Rails 3 autoload paths are not eager loaded in production. And in ruby 1.9 autoload is not threadsafe. You probably want eager loading in production. Requiring your lib explicitly, like in option 1, is akin to eager loading it, which is threadsafe.

    #### Option 3 (meh)

    All the different things under your lib dir should be placed into their own directories, and those directories should be individually added to `eager_load_paths`.

    ```
    config.eager_load_paths += %W(
    #{config.root}/lib/my_lib1
    #{config.root}/lib/my_lib2
    )
    ```

    This means that you can't just throw files into your lib dir. If you have `my_lib1.rb`, you must put it under `my_lib1/my_lib1.rb` and `my_lib1` should be added to eager load paths. This means that if you have more files in `my_lib1`, you should create a dir `my_lib1/my_lib1/extra.rb`. This is a bit annoying.

    #### So why not just add lib/ into `eager_load_paths`?

    If you add lib/ into `eager_load_paths`, everything will work great. Your files will be autoloaded in development, and eager-loaded in production. Except the problem is that `eager_load_paths` use globbing like `lib/**/*.rb`, meaning that everything in your lib dir will try to get loaded. Your tasks, your generators, everything. This is not what you want.

    #### Organizing lib

    In your lib/ dir you should structure your code as if you structure a gem. If you need more than 1 file, you could for example add a same-named directory where everything is properly namespaced, and let your 1 file relatively require files in that directory.
  10. maxim revised this gist Sep 10, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -19,7 +19,7 @@ If the answer is no, add `config.autoload_paths += %W( #{config.root}/app/models

    #### Option 1

    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just require it in your rake task. If you need this library to always be loaded for your rails app, you require it in an initializer. If you need this library for some of your models or controllers, you `require` it in those files, and since everything under your `app/` dir is already auto- and eager-loaded as needed, your library will only be "pulled-in" if a constant that requires it was triggered.
    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just `require` it in your rake task. If you need this library to always be loaded for your rails app, you `require` it in an initializer. If you need this library for some of your models or controllers, you `require` it in those files, and since everything under your `app/` dir is already auto- and eager- loaded as needed, your library will only be "pulled-in" if something that requires it from `app/` or rake, or your custom script, actually gets loaded.

    #### Option 2 (bad)

  11. maxim revised this gist Sep 10, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -19,7 +19,7 @@ If the answer is no, add `config.autoload_paths += %W( #{config.root}/app/models

    #### Option 1

    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just require it in your rake task. If you need this library to always be loaded for your rails app, you require it in an initializer. If you need this library for some of your models or controllers, you require it in those files, and since everything under your `app/` dir is already auto- and eager-loaded as needed, your library will only be "pulled-in" if a constant that requires it was triggered.
    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just require it in your rake task. If you need this library to always be loaded for your rails app, you require it in an initializer. If you need this library for some of your models or controllers, you `require` it in those files, and since everything under your `app/` dir is already auto- and eager-loaded as needed, your library will only be "pulled-in" if a constant that requires it was triggered.

    #### Option 2 (bad)

  12. maxim revised this gist Sep 10, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -19,7 +19,7 @@ If the answer is no, add `config.autoload_paths += %W( #{config.root}/app/models

    #### Option 1

    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just require it in your rake task. If you need this library to always be loaded for your rails app, you require it in an initializer. If you need this library for some of your models or controllers, you require it in those files, and since everything under your app is already auto- and eager-loaded as needed, in development your library will only be pulled in if a constant that requires it was triggered.
    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just require it in your rake task. If you need this library to always be loaded for your rails app, you require it in an initializer. If you need this library for some of your models or controllers, you require it in those files, and since everything under your `app/` dir is already auto- and eager-loaded as needed, your library will only be "pulled-in" if a constant that requires it was triggered.

    #### Option 2 (bad)

  13. maxim revised this gist Sep 10, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,7 @@ Do nothing. All files in this dir are eager loaded in production and lazy loaded
    (e.g. app/models/concerns/, app/models/products/)

    Ask: do I want to namespace modules and classes inside my new dir?
    For example in app/models/products/ you would need to wrap your class in a module Products.
    For example in app/models/products/ you would need to wrap your class in `module Products`.

    If the answer is yes, do nothing. It will just work.
    If the answer is no, add `config.autoload_paths += %W( #{config.root}/app/models/products )` to your application.rb.
  14. maxim revised this gist Sep 10, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@

    Do nothing. All files in this dir are eager loaded in production and lazy loaded in development by default.

    ### If you add a dir under app/\[something\]
    ### If you add a dir under app/something/

    (e.g. app/models/concerns/, app/models/products/)

  15. maxim revised this gist Sep 10, 2013. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,9 @@

    Do nothing. All files in this dir are eager loaded in production and lazy loaded in development by default.

    ### If you add a dir under app/\[something\] (e.g. app/models/concerns/, app/models/products/)
    ### If you add a dir under app/\[something\]

    (e.g. app/models/concerns/, app/models/products/)

    Ask: do I want to namespace modules and classes inside my new dir?
    For example in app/models/products/ you would need to wrap your class in a module Products.
  16. maxim revised this gist Sep 10, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@

    Do nothing. All files in this dir are eager loaded in production and lazy loaded in development by default.

    ### If you add a dir under app/[something] (e.g. app/models/concerns/, app/models/products/)
    ### If you add a dir under app/\[something\] (e.g. app/models/concerns/, app/models/products/)

    Ask: do I want to namespace modules and classes inside my new dir?
    For example in app/models/products/ you would need to wrap your class in a module Products.
  17. maxim created this gist Sep 10, 2013.
    28 changes: 28 additions & 0 deletions rails_load_path_tips.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,28 @@
    # In Rails 3

    ### If you add a dir directly under app/

    Do nothing. All files in this dir are eager loaded in production and lazy loaded in development by default.

    ### If you add a dir under app/[something] (e.g. app/models/concerns/, app/models/products/)

    Ask: do I want to namespace modules and classes inside my new dir?
    For example in app/models/products/ you would need to wrap your class in a module Products.

    If the answer is yes, do nothing. It will just work.
    If the answer is no, add `config.autoload_paths += %W( #{config.root}/app/models/products )` to your application.rb.

    ### If you add code in your lib/ directory


    #### Option 1

    If you put something in the lib/ dir, what you are saying is: "I wrote this library, and I want to depend on it where I decide." This means that if you use your library in a rake task, but not in a rails app, you just require it in your rake task. If you need this library to always be loaded for your rails app, you require it in an initializer. If you need this library for some of your models or controllers, you require it in those files, and since everything under your app is already auto- and eager-loaded as needed, in development your library will only be pulled in if a constant that requires it was triggered.

    #### Option 2 (bad)

    Another option is to add your whole lib dir into `autoload_paths`: `config.autoload_paths += %W( #{config.root}/lib )`. This means you shouldn't explicitly require your lib anywhere. As soon as you hit the namespace of your dir in other classes, rails will require it. The problem with this is that in Rails 3 autoload paths are not eager loaded in production. And in ruby 1.9 autoload is not threadsafe. You probably want eager loading in production. Requiring your lib explicitly, like in option 1, is akin to eager loading it, which is threadsafe.

    #### Organizing lib

    In your lib/ dir you should structure your code as if you structure a gem. If you need more than 1 file, you could for example add a same-named directory where everything is properly namespaced, and let your 1 file relatively require files in that directory.