Rails 3: Call functions inside controllers - ruby-on-rails

If I want to have functions to be called inside controllers, where should I put them?

if you want it to be local to a controller then all you need to do is to add it to the controller you wish to use.
private
def myfunction
function code.....
end
to all controllers you can put it inside the application controller, because all controlers are sub classed.
ApplicationController
protected
def myfunction
function code.....
end
If you want access in your views then you can create a helper
ApplicationHelper
def myfunction
function code...
end

#jonnii, for example, I want to call a function that returns a generated unique code.
If your generated code is going to be used only on your controllers, put the function inside a controller, as protected function (the easiest way would be putting it inside ApplicationController).
If you need to call the function on the views, then put it on a helper, like ddayan says.
If you also need to invoke the function from models, then the simplest way to do it is by putting a module inside the /lib/ directory.
# /lib/my_module.rb
module MyModule
def generate_code
1
end
end
You will also need to include it with an initializer:
#/config/initializers/my_module.rb
require 'my_module'
From that moment on, you can use the function like this:
MyModule::generate_code
If you are doing this very often, consider creating a gem.

class YourController < ActionController::Base
def your_action
your_function
end
private
def your_function
end
end
Also look at before_filter and after_filter, they're often useful in such kind of things

The ApplicationController is here for that, since every Controller inherited from it.

Related

Using a helper method to set an instance variable

I have several controllers that set an instance variable, as follows:
before_action :set_max_steam_pressure
.....
def set_max_steam_pressure
# and then about a dozen lines of code concluding with
#max_steam_pressure = Valve.where(id: socket_id).first.pressure
end
This code is repeated in about a dozen controllers.
Is it possible to do this through a helper method, as part of the before_action, without having to repeat the same code in all the controllers? Benefits: less code, and if I have to change something in the future, I would only do it in one place.
You can use "controller concern", for example:
app/controllers/concerns/steam_pressure_setup.rb
module SteamPressureSetup
extend ActiveSupport::Concern
included do
before_action: set_max_stream_pressure
end
def set_max_stream_pressure
# ...
end
end
Then include it in your controllers which need it.
app/controllers/my_controller.rb
class MyController < ApplicationController
include SteamPressureSetup
# ...
end
Ref: https://api.rubyonrails.org/classes/ActiveSupport/Concern.html

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) %>

How to include session in my custom lib file?

I know I will get answers that I shouldn't do this, but due to specific way to solve problem I am facing, I will have to use session in my /lib/example.rb file. (or at least I think I will have to use it)
I am calling an action, which will first run (seudo code):
module ApplicationHelper
def funcion(value)
MyClass.use_this(value)
end
end
And then I will use it in my lib/example.rb
module MyClass
# include SessionsHelper # this is not working
def self.use_this(value)
# I want to be able to use session here. What I need to do that in order to make it work.
session[:my_value] = value
end
end
What should I do in order to use session inside MyClass (I can pass variable to MyClass.use_this(value,session), but I wouldn't want to do that
Edit:
What I want to achieve with this session thing is that I would like to preserve a value during multiple requests. I am making a call to the web application multiple times, and I want to preserve some value on the next call. I am calling the app via API and I shouldn't use database to save values. So I have left with sessions, or text files, or even maybe cookies to make this happen - to preserve the same value on multiple calls.
Why not include the module in your controller, and then call the use_this function directly from there?
module MyClass #should probably rename this anyway
def use_this(value)
session[:my_value] = value
end
end
class SomeController < ApplicationController
include MyClass
def some_action
...
use_this(the_value)
...
end
end
In order to use session inside MyClass may be you could use instance variable #session:
module MyClass
extend SessionsHelper
def self.use_this(value)
#session[:my_value] = value
end
end
module SessionsHelper
def some_method
#session = ...
end
end
self.include(module) method makes the instance methods (and instance variables) of the included module into instance methods of the including module.
Edit: include SessionsHelper changed to extend SessionsHelper
self.extend(module) -- methods of receiver become class methods of that class and instance variables will work between this methods.

In Rails, where to put useful functions for both controllers and models

Suppose I have a function trim_string(string) that I want to use throughout my Rails app, in both a model and a controller. If I put it in application helper, it gets into the controller. But application helper isn't required from within models typically. So where do you put common code that you'd want to use in both models and controllers?
In answer to the specific question "where do you put common code that you'd want to use in both models and controllers?":
Put it in the lib folder. Files in the lib folder will be loaded and modules therein will be available.
In more detail, using the specific example in the question:
# lib/my_utilities.rb
module MyUtilities
def trim_string(string)
do_something
end
end
Then in controller or model where you want this:
# models/foo.rb
require 'my_utilities'
class Foo < ActiveRecord::Base
include MyUtilities
def foo(a_string)
trim_string(a_string)
do_more_stuff
end
end
# controllers/foos_controller.rb
require 'my_utilities'
class FoosController < ApplicationController
include MyUtilities
def show
#foo = Foo.find(params[:id])
#foo_name = trim_string(#foo.name)
end
end
It looks like you want to have a method on the String class to "trim" itself better than a trim_string function, right? can't you use the strip method? http://www.ruby-doc.org/core-2.1.0/String.html#method-i-strip
You can add new methods to the string class on an initializer, check this In Rails, how to add a new method to String class?
class String
def trim
do_something_and_return_that
end
def trim!
do_something_on_itself
end
end
That way you can do:
s = ' with spaces '
another_s = s.trim #trim and save to another
s.trim! #trim itself
but check the String class, it looks like you already have what you need there

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).

Resources