What do helper and helper_method do? - ruby-on-rails

helper_method is straightforward: it makes some or all of the controller's methods available to the view.
What is helper? Is it the other way around, i.e., it imports helper methods into a file or a module? (Maybe the name helper and helper_method are alike. They may rather instead be share_methods_with_view and import_methods_from_view)
reference

The method helper_method is to explicitly share some methods defined in the controller to make them available for the view. This is used for any method that you need to access from both controllers and helpers/views (standard helper methods are not available in controllers). e.g. common use case:
#application_controller.rb
def current_user
#current_user ||= User.find_by_id!(session[:user_id])
end
helper_method :current_user
the helper method on the other hand, is for importing an entire helper to the views provided by the controller (and it's inherited controllers). What this means is doing
# application_controller.rb
helper :all
For Rails > 3.1
# application.rb
config.action_controller.include_all_helpers = true
# This is the default anyway, but worth knowing how to turn it off
makes all helper modules available to all views (at least for all controllers inheriting from application_controller.
# home_controller.rb
helper UserHelper
makes the UserHelper methods available to views for actions of the home controller. This is equivalent to doing:
# HomeHelper
include UserHelper

A Helper method is used to perform a particular repetitive task common across multiple classes. This keeps us from repeating the same piece of code in different classes again and again.
Here's an example to simplify the above definition:
Here is a code, where you would have something like this in the view:
<% if #user && #user.email.present? %>
<%= #user.email %>
<% end %>
We can clean it up a little bit and put it into a helper:
module SiteHelper
def user_email(user)
user.email if user && user.email.present?
end
end
And then in the view code, you call the helper method and pass it to the user as an argument.
<%= user_email(#user) %>
This extraction makes the view code easier to read especially if you choose your helper method names wisely.
So I hope this clears things up a little for you.
Source for the quotation
Source for the code

Related

Add helper to rails controller instance only

I have some helpers that are defined on runtime that are specific for a single call, e.g. a single instance of a controller (the next call could have different helper methods). Is there a robust way to add a helper method to an instance of a controller and it's view only, without adding the helper to other instances and views of this controller?
To define a helper for ALL instances, you could use the .helper_method method, e.g.
class Article < ApplicationController
helper_method :my_helper
def my_helper
# do something
end
end
I digged around in the source code, and found the (fairly private looking) #_helpers method which returns a module that contains all helpers for this instance. I could now use some meta programming to define my methods on this module
def index
_helpers.define_singleton_method(:my_helper) do
# do something
end
end
But I don't like this approach because I'm using a clearly private intended method that could easily change in the future (see the leading _).
If I only needed the helper inside the controller instance only, I could just call #define_singleton_method on the instance directly, but this doesn't make it available to the view.
So I'm looking for an official "Rails way" to define a helper for a single instance of a controller and it's view, like Rails provides with it's class method .helper_method.
I'm not sure if there is an official Rails way of doing this.
You could create an anonymous module and extend from that. Since this solution uses pure Ruby, you'll have to extend both the controller and view.
before_action :set_helpers, only: :index
def index
# ...
end
private
def set_helpers
#helpers = Module.new do |mod|
define_method(:my_helper) do
# do something
end
end
extend(#helpers)
end
<% extend(#helpers) %>

Logic for Application Layout

I am trying to make an ActiveRecord call to get information for the application layout (the default application.html.haml layout). I know I am not supposed to put logic into the layout itself, but I am unsure of where to put it.
The line of code I need run in the layout is just a simple Model call:
Client.find_by(:id => current_user.client_id)
I would suggest throwing it in helpers/application_helper.rb. I've used this in the past for things such as title helpers and body class helpers.
# helpers/application_helper.rb
module ApplicationHelper
def body_class
[controller_name, action_name].join(' ')
end
end
# views/layouts/application.slim
body class=body_class
= yield
The ApplicationController isn't for such helpers. It's mainly as support for your controllers, not your views.
It's okay if you put it in ApplicationController. And you can put controller related code to controllers/concerns folder.
'concerns/concern.rb':
module Concern
def method
# Your code here
end
end
To use a module from concerns folder include it in the controller: include Concern

Separate rails helper methods

I have a couple of controllers with associated helper modules. I got some helper methods that should behave similarly across different modules, meaning:
module UserHelper
..
def destroy(user)
link_to t(:destroy_user), user ...
end
end
module PhotosHelper
..
def destroy(photo)
link_to t(:destroy_photo), photo ...
end
end
I didn't know (realize) that all of these helper modules are included by default, (which is ok, I guess,) and it doesn't matter what view you're calling the helper method from.
What is the best way to separate the rest of the helpers from my current controller/view so that, when controller_name == 'photos', only Photos and Application helpers are used?
The concept of Helpers is not really clear to me. Why not just have a single ApplicationController if all helpers are already mixed in? Is it just for "logical separation"?
I mean, of course, there's a number of workarounds. But is it just me, or it really feels like there's no reason to include all of the helpers globally?
If you called clear_helpers at ApplicationController class, they won't share among different helper classes
clear_helpers()
Clears up all existing helpers in this class, only keeping the helper with the same name as this class.
ref: http://api.rubyonrails.org/classes/AbstractController/Helpers/ClassMethods.html#method-i-clear_helpers
You could put the common methods on the ApplicationHelper and pass the resource as a parameter.
So then use the specific helper resource for specific methods only.
Methods (helpers) that you can share anyway, goes to ApplicationHelper file.

Controller calls the helper

I have an easy question:
Where to put the helper methods that is called many times by a controller ?
My wish is to keep clear my controller ( user_controller) and I have an helper methods that is called many times (check_permits)
is it possible to put this method inside user_helper ?
If yes ==> how to recall it inside user_controller ? If I simply recall check_permits it doesen't recognize it.
If no ==>, where to put the helper methods ?
You are using confusing terminology. In rails, controllers do not have helpers. Helpers are defined as being for the views. It's possible to call helper methods from a controller by using the "helpers" method (see http://api.rubyonrails.org/classes/ActionController/Helpers/ClassMethods.html), but I don't think that's what you're looking for (and generally that's not a good idea anyway).
What you probably want is to either (1) put the method directly in your users_controller.rb as a protected method:
class UsersController < ApplicationController
...
protected
def check_permits
...
end
end
Or (2) put it in the application_controller.rb if you call it from multiple controllers.
Or (3) put it in a library file as a module and include it in whatever controllers need it. For example, you might create lib/check_permits.rb:
module CheckPermits
protected
def check_permits
...
end
end
And then in users_controller.rb:
class UsersController < ApplicationController
include CheckPermits
...
end
You can put global helper methods in the application_helper.rb file, but if it's only to be used by one controller each controller can have it's own helper file. Look in app/helper (or app/controller/helper).

How do I dynamically create a named_route in rails?

I currently have this in my ApplicationController
def account_path
eval "#{current_user.type.downcase}_account_path"
end
I use it for redirects, etc. But I also want to use it in the view (for link_to's etc). Is this is a legit case to share code between the controller and view to keep it DRY even though it breaks MVC?
Yes, I'd say that's a legitimate re-use. The helper_method call is there for a reason so:
helper_method :account_path
will make this available to your views too.
If you prefer not to use eval you could do:
def account_path
self.send("#{current_user.type.downcase}_account_path")
end
as the _path method is interpreted as a method on the controller.

Resources