In an attempt to be more object-oriented, I find myself creating more POROs (Plain-old_ruby-objects). In rails, this simply means that the model class does not inherit from ActiveRecord::Base, and thus this model is not backed by a database table.
Lets say I have an app with hundreds of models. It would be nice if there was some naming convention of PORO models so that those PORO models can be quickly identified instead of having to open up each of their files and notice that they do not inherit from ActiveRecord::Base.
I could not find a naming convention for this. Does one exist in the rails community? If not, suggestions are welcome.
What I ended up doing was creating a subdirectory in my app/models directory called: poros.
In order to make those files within that poros subdirectory available within the load path, I had to go into config/application.rb and add this line:
config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]
Now I can access those POROs just like I can with any of the Models.
I'm not aware of any naming convention for poro classes in the Rails community, even though there has been a recent trend to keep classes inheriting from ActiveRecord::Base rather small.
If your classes are rather generic, they should be placed in the lib directory. If they are specific to your app but only require no interaction with other classes, you could create service classes placed in app/services. Similarly you can extract decorators, jobs and concerns.
Whatever classes remain can either stay in the appfolder, or be placed in a subdirectory.
Related
I am working on a project where the current developers have put their "Plain Old Ruby Objects" in the models directory of our Rails app.
I have seen most examples online where the PORO files go inside lib instead, but some say models.
Is there even a logical / specific reason why people put them in the models directory over the lib directory?
"Idiomatically" the models directory intended for code used to hold state. Most of the time this would be ActiveRecord subclasses corresponding to database tables. However frequently people put other stuff in the models directory. One thing often seen are code dropped here in order to take advantage of auto-reloading. (the lib dir doesn't normally auto-reload)
Based on the Getting Started Rails guide, the app/models/ directory is pretty much anything, whereas lib/ is for modules that are used across the entire app (e.g. extensions).
As #seand said, yes, one advantage is that the app/models/ directory automatically reloads, but I tend to think of it as any class that "interacts with other classes" should live in app/models/, with the only exception being a service class (which I tend to think of as "a class which manipulates the state of another class"), which I tend to put into app/services/.
I know a lot of developers would disagree with me - many I've talked to even create a separate directory namespaced to their app (e.g. if your app is named "MyBlog", they would create an app/myblog directory for any object not explicitly backed by the database, but not a module or a service class either.
That said, I think ultimately it boils down to a) personal preference and b) where you feel is best to place the PORO with respect to your app.
There is no hard and fast rule on where to put POROs. The rails community has been hashing this out for a while now. At one point the convention was to put stuff in the concerns directory but that seems to have fallen out of favor with some folks.
One rule of thumb for the difference between /lib and app/{blah} is that code in the /lib folder is code that you presumably can reuse across several projects e.g. general purpose class or utilities. for example if you have some custom monkey patches to core ruby or rails classes that you will use in multiple projects, a good place to but them would be in the lib folder. Anything in app/{blah} should pertain specifically to current project.
One way to think of lib folder is as the poor cousin of plugins and gems.
Just my 2 cents on the subject
I am using Ruby on Rails 3.2.2 and I would like to organize and share custom helper-view methods as-like I made for my view files. That is, in my app/views directory I have a shared folder where I put all shared templates and I would like to have a shared folder (intended to be used the same "sharing way" but for helper files) also in the app/helpers directory.
However, my doubts are:
Is right to share helper methods instead of putting those in the ApplicationHelper module (even if those helper methods are specific for shared views and not directly related to any model or controller)?
How can I load modules present in the app/shared/helpers directory in order to make those available to views?
Is there some prescriptions to this approach?
In Rails, helpers are actually global. Which means that you can call a user helper in a, say, posts view. So you don't really have to pollute ApplicationHelper, just divide them in the best way possible, and just use them normally.
In Rails, I can create models which are global (accessible anywhere in the application). However, I'd like to create some constructs that are global, but don't correspond to any database table (which is why they can't be models) and won't ever be instantiated (so I need modules instead of classes).
I've tried using the initializers directory, which works, but is annoying because it requires restarting my server every time I change a value (whereas I can change the code in my models without restarting the server). What's the best way to create globally-accessible modules in this manner?
Just put it into lib sub-directory and add that to your config/application.rb:
config.autoload_paths += ["#{config.root}/lib"]
In addition to adding modules to the lib directory (which is appropriate), you can also put classes in the models directory. They don't have to be ActiveRecord based.
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.
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