How do you organize the different types of helper code in Rails? Or, more generally speaking, am I supposed to have only view helpers outside the main files for a particular model/view/controller?
Here's what I mean: I have joined a team working on a large Rails app. As far as I can see, all the files in app/helpers
are view helpers, that can be included in controllers and mailers via add_template_helper(HelperName)
or helper :helper_name
.
But imagine this situation - you want to split a large mailer into several smaller mailers. In the large mailer you have defined several helper methods. Now you want to access these helper methods also in the new mailers.
How do you go about it?
Should you create a new module/file, put it under app/helpers
and then use it via include HelperName
or is there another convention for this?
I have not stumbled upon this yet, but I imagine there might be some model helpers as well, that I want shared between several models, so I would like to know how to organize them as well.
Edit: After some reading I realized that just including a method in a controller or a mailer introduces the problem that this method becomes a controller/mailer action. So I guess this is also a more general Ruby question - how do I share methods between several classes, while keeping this methods private. If class A, B, and C must have method foo, do I declare it three times as a private method within the class definitions of A, B and C or can I define it in a module, include the module in the classes A, B, and C, but then again keep it private?
Yes, you can make a method private in a module, include the module in multiple classes and use it in them. In Ruby private
means that the method can only be called without a receiver. A private method in a module can be called by instance methods in the class it's included in or by methods in the same module or other modules in the same class.
So modules are a good way to break up large classes and share code in Rails and in Ruby in general.
Regarding Rails code organization,
"helper" refers specifically to a module containing methods that are used in views. Helpers live in app/helpers.
Rails 4 has "concerns", which live in app/controllers/concerns and app/models/concerns. A concern is just a module, meant to be included in a controller or model, that extends ActiveSupport::Concern
(which handles some common patterns in module setup).
If for some reason you need a shared module or class that isn't a helper or concern, just put it in the same directory as the classes/modules that use it and use it however you like.
If you have a whole category of classes/modules that don't fit the existing Rails directory structure (such as reports, use case controllers, or facades to external services), you can make a new directory under app, add it to config.autoload_paths
in application.rb, and put your new family of classes/modules there.