Guidelines for calling controller methods in helper modules? - ruby-on-rails

Few questions:
Is it possible to call a controller method in a helper module (e.g., application helper)?
If so, how does the helper handle the rendering of views? Ignore it?
In what instances would you want to call a controller method from a helper? Is it bad practice?
Do you have any sample code where you're calling controller methods in helper?

You generally don't call controller-methods from helpers. That is: if you mean a method that collects data and then renders a view (any other method that needs to be called should probably not be in a controller).
It is definitely bad practice and breaks MVC.
It is, however, perfectly possible to make controller-methods available in the views, a great example is for instance the current_user method.
To make a controller method available in the views, as a helper method, just do
private
def current_user
# do something sensible here
#current_user ||= session[:user]
end
helper_method :current_user
Such a method is best defined in the private section, or it could be available as an action (if you a wildcard in your routing).

Declare your methods on the corresponding controller
private
def method_name1
...
end
def method_name2
...
end
In the head of the controller declare
helper_method :method_name1, :method_name2
You may want to declare those methods under private state
And that's it, now you can use your method on a helper

Calling a controller from a helper violates the MVC pattern. IMO if you need to call a controller from a Rails view helper (like application_helper) then there is something about the design that could be improved. The intention is that helpers "help" views, and therefore only talk to models.
I'm not going to defend MVC itself here (there are a ton of references on the web), but this SO thread about calling the controller from a view should get you started.
Calling controller from view? (note, this is an ASP.NET thread, so only the high level principles are relevant).

Related

what should I define in application controller in ruby in rails?

I don't know exactly why application_controller needs in ruby on rails
my idea is...
I had watched Ruby on Rails guide, I can find out route_not_found method is in application controller, and this method can used in other controllers.
so I thought application controller is different from normal controller, and this controller is for other controller.
def route_not_found
render file: Rails.public_path.join('404.html'), status: 404, layout: false
end
and method in application controller can be used as before_action's argument in other controller. I had defined not_login? method,
def not_login?
if current_user.nil?
redirect_to login_path, notice: 'You have to log in'
end
end
like this, and I can used this method in other controller as before_action's argument.
so I thought application_controller is for defining method which used for before_action.
is my thinking correct?
I want to know what application controller's true usage
Application controller helps abstract out shared logic of the controllers in your project. You can use it for various application wide tasks such as error handling, common methods, setting before actions, setting helper methods, etc.
As mentioned, methods that are used by multiple controllers can be placed here (ex. def current_user). However, if a method is only shared by a few controllers within a domain, it is better to place it into a different parent controller in that same domain to keep things organized.
In this example, the controllers would inherit from the custom parent controller and the custom parent controller would inherit from application controller.
You can set before actions in application controller and call them from application controller as well, just define the method and call before_action :method_name at the top of the application controller. That before action will run before all controller actions. If you only want it to run on certain controllers, then call it the way you described, just from the controller where you want it.

Call inner controller actions and send params between them rails

I'm creating an API and I want that the outside can only has access to update method to actualize a report. But in case there is no report I want to create it. I know that the easy way to do it is just create it inside update method, but as soon I have already a create method build I was wondering if is it possible to call it sending it also some params.
I looked around like here Rails 3: Call functions inside controllers or the API but I didn't found any good solution.
Does anyone has a better one?
Thank you very much in advance.
You should not call an action of your controller from another action.
Why? Because every action of a controller is defined to respond to a request, which has several attributes (such as IP, params, session, HTTP headers, etc.). Imagine how "weird" it would be to call an action from another in the Controller.
If you want to do "extra logic" which would not be related to the update action (for example, create), you should call a protected (accessible only via the Controller & its children) method of this controller.
In your case, you could do something like this:
class ReportsController < ApplicationController
def update
#report = Report.where(id: params[:report_id]).first
if #report.nil?
create_report(params)
else
# etc.
end
end
protected
def create_report(params)
Report.create(params)
end
end

How do I use layouts and view scripts outside of controllers?

I'm creating a new class, not a controller, nor a model, nor a mailer, that will act as a sort of controller.
It will have a render method that will need to render an HTML view script and layout associated with this class.
How can I utilize what Rails already provides in my class to render these views?
AbstractController, specifically AbstractController::Rendering is probably what I would look at first. There's likely something you can use there.

Calling a Controller Action from a View... Or not?

I'll keep it short: Should I call Controller2.getByCriteria(some, criteria, here) from Controller1 then set an instance variable for the view to use, or should I call it from Controller1's view using something like = render Controller2.getByCriteria(some, criteria, here)?
Generally speaking, calling one controller's action from another is a design error. It either means you have common business logic, which implies the code should be in models (or maybe lib) or you have common view logic, which implies the code should be in helpers.
So in your case, I think using a helper seems apt:
module ApplicationHelper
# ...
def getByCriteria(some, criteria, here)
# handle criteria here
# Something like:
# render :partial => 'foo'
end
# ...
end
And then simply call it from the views.
If you want a full controller/view like component sharing across your application, you can use a gem called cells. It enables you to create re-usable controller and view components.
The proper way to do this is to declare the controller method (not controller action) as a helper.
See here.

Is it possible to utilize internal methods on controllers to reduce duplication?

in a partial view I have the following:
<%Html.RenderAction(MVC.User.GetComments(Model.UserGroupName)); %>
can I render a Controller's PartialViewResult in a View without going through routing so I can pass arguments directly from the model so that the arguments I'm passing to the controller never get sent to the user or seen by the user?
Currently the method I'm showing at the top throws an exception because no overload is public. I've got it marked as internal so that a user can not access it, only the rendering engine was my intent.
Slap a [ChildActionOnly] attribute on any action method if you want that method to be callable only by RenderAction() rather than the outside world. Or - if you have a whole controller of such methods - slap the attribute on the controller itself.

Resources