Where's the recommended location for libraries in Rails 3? Is it as simple as 'lib'?
I'm not sure because 'lib' seems more like a Rails 2 remnant, especially considering that it's no longer auto-loaded (and there was a lot of discussion about that, apparently).
Initializers are more for (obviously) initialization tasks such as overrides.
Specifically I have a small module for attachment handling (Paperclip doesn't fit here) that's too large and distinct to include in my model, but not generic or worthwhile enough to implement as a gem.
From a functionality standpoint it lives somewhere in the middle among the model, view, and controller. This makes it sound like a helper, but in Rails helpers are intended for views AFAIK.
Should I just put it in 'lib' and autoload it in application.rb? Or maybe I could create a custom form builder to handle the presentation (or both).
I know how to make it work, but I'm hoping to learn something new. :)
lib is still the right place to put these kind of things.
Autoloading lib was removed in Rails 3 because of the way engines work, but mainly because it's easy to just add it to the autoload_paths if you do want it automatically loaded and if not, you can require as needed. lib is still in the load path, so you don't need to specify where the module or class you're requiring is.
You're correct, helpers are intended for the view, and would not be the place to put any model-related logic.
I'd put the module in lib, and require and include it in your model as needed.
Related
In the sidekiq documentation, there is this quote about preferring to use /app/lib instead of /lib in Rails projects related to autoloading errors:
A lib/ directory will only cause pain. Move the code to app/lib/ and make sure the code inside follows the class/filename conventions.
Additionally, there is also:
Don't configure extra paths in autoload_paths or eager_load_paths. That's a hack; follow the conventions! Any directory underneath app/ may contain Ruby code, you don't need to explicitly configure anything.
My questions are:
Is there any truth to these statements that using /app/lib is better than /lib?
Is this only helpful for autoloading Rails-related objects (such as AR models, controllers, jobs, etc)? Or will it also help POROs?
Is there only a specific context in which these comments make sense?
In my experience app/lib is easier to use. You can literally stick in something like Class MathFunction and use it elsewhere (e.g. controllers or modules) with MathFunction.sqrRoot.
To use /lib you need to configure your Rails app with autoload_paths. autoload_paths also need some tweaking to work properly in production. Matz himself discourages autoload because it's in the process of being deprecated.
The only time I've needed to use the lib directory is for making custom rake tasks. Otherwise I stick to app/lib.
I'm using rails31 & coffeescript and have defined some classes that extend from a parent class. Coffeescript adds an __extends helper method in the generated output to make this happen, problem is when using sprockets a copy of the method is added for every subclass, creating a lot of duplication.
My classes are defined in separate files, so it looks like sprockets is getting coffee to process them individually. I know there is a —join option with coffee but not sure how to use that with sprockets.
Does anyone know if it's possible to generate coffee helpers only once when using sprockets?
Nope. Whether you're using Sprockets or not, helpers are a one-per-file kind of deal. There's no compiler option for avoiding this duplication (--join won't do it; it just concatenates the compiled JS), and no existing JS minifier is smart enough to identify and remove the duplicates (which would require moving one instance to a global scope).
My advice would be to not worry about it. CoffeeScript uses few helpers, and they're unlikely to account for more than a tiny fraction of your code.
I feel like I understand the difference between require and require_dependency (from How are require, require_dependency and constants reloading related in Rails?).
However, I'm wondering what should happen if I use some of the various methods out there (see http://hemju.com/2010/09/22/rails-3-quicktip-autoload-lib-directory-including-all-subdirectories/ and Best way to load module/class from lib folder in Rails 3?) to get all files loading so we:
don't need to use require_dependency all over the place in the application and
don't have to restart development servers when files in the lib directory change.
It seems like development performance would be slightly impacted, which is not that big of a deal to me. How would performance be impacted in a production environment? Do all of the files generally get loaded only once if you are in production anyway? Is there a better way that I'm not seeing?
If you could include some resources where I could read more about this, they would be greatly appreciated. Some blog posts said that this behavior changed recently with Rails 3 for autoreloading lib/* files and that it was contentious, but I didn't see any links to these discussions. It would be helpful for considering the pros/cons. Thanks!
The code reloader is disabled by default in production. So if you are calling require_dependency at the top of a file it is going to be executed only once.
The Rails 3 change you mentioned is really small. You can usually call Foo and it will be loaded from app/models/foo.rb automatically. Before it could also be loaded from lib/foo.rb. (These directories app/models and lib are called autoload paths.) Rails team decided to remove lib from autoload paths in the 3rd version. You can still put it back. But it is encouraged to leave in lib less frequenttly-changed and project-specific files. If you have something that does not belong to any of the default app subdirectories like app/models or app/controllers you don't have to put it in lib. You can add your own subdirectory. I have app/presenters, for example. There is a discussion on the old issue tracker if you want more info on that.
What are the reasons putting a module in /helpers over the /lib folder in a RoR app?
Are /helpers more controller specific, while the /lib is more general in nature?
I think this is a good question because the MVC notion makes us forget that it's all really just metaphors for us to organize code so we don't get too mixed up. If you need to do some simple formating go with a helper, otherwise probably a module in /lib.
Helpers are strictly for defining methods that you want available in your views. /lib modules can be used for anything and are available throughout the application.
Some functionality within my rails application looks better as if it was a separate "module", that should be accessed via require. For example, assume it's a function to calculate Fibonacci numbers.
The functionality is independent on rails application and can be reused in other projects, so it should not be stored near application controllers and models, I suppose. But since I'm not going to detach it into separate project, thus placing it to vendor folder seems like not the right thing.
Where should I place it then?
Rails < 5
Before Rails 5, the place to put reusable code such as this is in the lib directory. However you do not need to require anything as lib is already in the load path and it's contents will be loaded during initialization.
If you need to extend an existing class, you define your module first and then include it by sending it as a message to the class you wish to extend, e.g.
module MyExtensions
def self.included base
base.instance_eval do
def my_new_method
…
end
end
end
end
ActiveRecord::Base.send :include, MyExtensions
Rails 5+
The answer is for Rails 5 onwards. TLDR: app/lib is the convention now.
Note all the above answers were written before Rails 5.
\lib
Rails 5 discourages you from using \lib. While you are discouraged from using \lib you still can as long as you add \lib to eagerloading.
# config/application.rb
config.eager_load_paths << Rails.root.join('lib')
\app\lib
Nesting lib off app is now a common convention because any directory off app is automatically eagerloaded.
Reference
Rails guide - autoloading and eagerloading
Stackoverflow - confusing about autoload_paths vs eager_load_paths in rails 4
Stackoverflow - Why use app-lib instead of lib in rails
There is a lib directory in RoR projects which fits well for that purpose - I place common bits of code in form of "libraries" there. Anything from extending ActiveRecord classes to reusable utility methods.
I'll often put stuff in lib, it turns out that anything under lib is in the load path and doesn't need to be required at all.
edit: After Steve's comment, removed the bit about having to require the files. Also, removed a couple requires from some of my code :P