Where should I store common function at? - ruby-on-rails

I have three models.
users_controllers.rb
communities_controller.rb
community_tipics_controller.rb
I'm using the function called check_digit
def checkdigit
(transaction)
end
and I'm placing this in all the controllers.and calling it by before_filter.
But I think I'm wasting because I'm just pasting exactly the same code above to all of the controllers.
Where am I supposed to put it if my controller is using it in common?
Should I put it in controllers/application_controller.rb?

There are several ways of doing this , some possible ways are (If I'm to do this)
1st method
If this is a simple method used by controllers
inside application_controller.rb
private
def checkdigit
(transaction)
end
2nd method
if your function is used by a specific category , (this is normally I do very often), create a separate controller and have your all other controllers inherited by it
Ex: if your method used only my admins, and assuming you have some more methods like that
class AdminController < ApplicationController
layout 'admin'
private
def checkdigit
(transaction)
end
end
and
class UsersController < AdminController
end
3rd method
If your method is/will used by models/controllers etc.. consider making it a module
module CommonMethods
def checkdigit
(transaction)
end
end
class UsersController < ApplicationController
include CommonMethods
end
HTH

You can put it in helpers/application_helper.rb

You are correct, all common methods that all controllers need should be stored in the ApplicationController.
Furthermore, you should also keep common logic between all controllers in this controller.
Edit:
If they are just helpers, then you would put them where the helpers go, see the answer by #simone.

Related

Create an "includable" Rails controller action within helper

Is it possible to make an includable controller action within a Rails Helper through an included block? I'm thinking something like this:
module XablauHelper
included do
def my_shared_action
true
end
end
end
Already tried doing it through class.eval block and through using like a class method i.e. self.my_shared_action but no success, I have already found a solution that is making a parent controller with the desired shared actions and inheriting from it, but for the sake of modular design I would like to make it a more "global" approach, so I could gemify my solution and reuse code, any suggestions that doesn't use inheritance?
Adding controller actions in a helper is probably the wrong choice, as these methods are intended for your views.
Consider using controller concerns instead, and including them where required. For example:
# in app/controllers/concerns/useful_functions_concern.rb
module UsefulFunctionsConcern
extend ActiveSupport::Concern
included do
rescue_from SomeException, with: :handle_access_denied
end
def useful_method
# ...
end
protected
def handle_access_denied
# ...
end
end
# in your controller
class XyzController < ApplicationController
include UsefulFunctionsConcern
def index
useful_method
end
end
Where common controller actions can be shared and the controllers have something in common e.g. they are all API controllers, also consider using inheritance to achieve this. For example:
# parent controller
class ApiController < ApplicationController
def my_shared_action
end
end
class SpecificApiController < ApiController
end

Rails: Methods shared by multiple controllers

I have two controllers, i.e
1) carts_controller
2) orders_controller
class CartsController < ApplicationController
helper_method :method3
def method1
end
def method2
end
def method3
# using method1 and method2
end
end
Note: method3 is using method1 and method2.
CartsController has showcart.html.erb view which is using method3 and works fine.
Now in order's view, I need to display cart (showcart.html.erb) but as the helper method3 is defined in carts_controller so it cannot access it.
How to fix it ?
As you are using Rails 4 (This approach should work in newer versions of Rails as well), the recommended way of sharing code among your controllers is to use Controller Concerns. Controller Concerns are modules that can be mixed into controllers to share code between them. So, you should put the common helper methods inside the controller concern and include the concern module in all of your controllers where you need to use the helper method.
In your case, as you want to share method3 between two controllers, you should put it in a concern. See this tutorial to know how to create concern and share codes/methods among controllers.
Here are some codes to help you get going:
Define you controller concern:
# app/controllers/concerns/your_controller_concern.rb
module YourControllerConcern
extend ActiveSupport::Concern
included do
helper_method :method3
end
def method3
# method code here
end
end
Then, include the concern in your controllers:
class CartsController < ApplicationController
include YourControllerConcern
# rest of the controller codes
end
class OrdersController < ApplicationController
include YourControllerConcern
# rest of the controller codes
end
Now, you should be able to use method3 in both controllers.

Calling a method from another controller

If I've got a method in a different controller to the one I'm writing in, and I want to call that method, is it possible, or should I consider moving that method to a helper?
You could technically create an instance of the other controller and call methods on that, but it is tedious, error prone and highly not recommended.
If that function is common to both controllers, you should probably have it in ApplicationController or another superclass controller of your creation.
class ApplicationController < ActionController::Base
def common_to_all_controllers
# some code
end
end
class SuperController < ApplicationController
def common_to_some_controllers
# some other code
end
end
class MyController < SuperController
# has access to common_to_all_controllers and common_to_some_controllers
end
class MyOtherController < ApplicationController
# has access to common_to_all_controllers only
end
Yet another way to do it as jimworm suggested, is to use a module for the common functionality.
# lib/common_stuff.rb
module CommonStuff
def common_thing
# code
end
end
# app/controllers/my_controller.rb
require 'common_stuff'
class MyController < ApplicationController
include CommonStuff
# has access to common_thing
end
Try and progressively move you methods to your models, if they don't apply to a model then a helper and if it still needs to be accessed elsewhere put in the ApplicationController
If you requirement has to Do with some DB operations, then you can write a common function (class method) inside that Model. Functions defined inside model are accessible across to all the controllers. But this solution does to apply to all cases.
I don't know any details of your problem, but maybe paths could be solution in your case (especially if its RESTful action).
http://guides.rubyonrails.org/routing.html#path-and-url-helpers

"undefined method" when calling helper method from controller in Rails

Does anyone know why I get
undefined method `my_method' for #<MyController:0x1043a7410>
when I call my_method("string") from within my ApplicationController subclass? My controller looks like
class MyController < ApplicationController
def show
#value = my_method(params[:string])
end
end
and my helper
module ApplicationHelper
def my_method(string)
return string
end
end
and finally, ApplicationController
class ApplicationController < ActionController::Base
after_filter :set_content_type
helper :all
helper_method :current_user_session, :current_user
filter_parameter_logging :password
protect_from_forgery # See ActionController::RequestForgeryProtection for details
You cannot call helpers from controllers. Your best bet is to create the method in ApplicationController if it needs to be used in multiple controllers.
EDIT: to be clear, I think a lot of the confusion (correct me if I'm wrong) stems from the helper :all call. helper :all really just includes all of your helpers for use under any controller on the view side. In much earlier versions of Rails, the namespacing of the helpers determined which controllers' views could use the helpers.
I hope this helps.
view_context is your friend, http://apidock.com/rails/AbstractController/Rendering/view_context
if you wanna share methods between controller and view you have further options:
use view_context
define it in the controller and make available in view by the helper_method class method http://apidock.com/rails/ActionController/Helpers/ClassMethods/helper_method
define it in a shared module and include/extend
Include ApplicationHelper in application_controller.rb file like this:
class ApplicationController < ActionController::Base
protect_from_forgery
include ApplicationHelper
end
This way all the methods defined in application_helper.rb file will be available in the controller.
You can also include individual helpers in individual controllers.
Maybe I'm wrong, but aren't the helpers just for views? Usually if you need a function in a controller, you put it into ApplicationController as every function there is available in its childclasses.
As said by gamecreature in this post:
In Rails 2 use the #template variable.
In Rails 3 use the controller method view_context
helpers are for views, but adding a line of code to include that helper file in ApplicationController.rb can take care of your problem. in your case, insert the following line in ApplicationController.rb:
include ApplicationHelper
As far as i know, helper :all makes the helpers available in the views...
Try appending module_function(*instance_methods) in your helper modules, after which you could directly call those methods on the module itself.
though its not a good practice to call helpers in controller since helpers are meant to be used at views
the best way to use the helpers in controller is to make a helper method in application_controller and call them to the controller,
but even if it is required to call the helper in a controller
then Just include the helper in the controller
class ControllerName < ApplicationController
include HelperName
...callback statements..
and call the helper methods directly to the controller
module OffersHelper
def generate_qr_code(text)
require 'barby'
require 'barby/barcode'
require 'barby/barcode/qr_code'
require 'barby/outputter/png_outputter'
barcode = Barby::QrCode.new(text, level: :q, size: 5)
base64_output = Base64.encode64(barcode.to_png({ xdim: 5 }))
"data:image/png;base64,#{base64_output}"
end
Controller
class ControllerName < ApplicationController
include OffersHelper
def new
generate_qr_code('Example Text')
end
end
hope this helps !
I had the same problem...
you can hack/bodge around it, put that logic into a model, or make a class specially for it. Models are accessible to controllers, unlike those pesky helper methods.
Here is my "rag.rb" model
class Rag < ActiveRecord::Base
belongs_to :report
def miaow()
cat = "catattack"
end
end
Here is part of my "rags_controller.rb" controller
def update
#rag = Rag.find(params[:id])
puts #rag.miaow()
...
This gave a catattack on the terminal, after I clicked "update".
Given an instantiation, methods in the model can be called. Replace catattack with some codes. (This is the best I have so far)
:helper all only opens helpers up to views.
This shows how to make a class and call it.
http://railscasts.com/episodes/101-refactoring-out-helper-object?autoplay=true
Try this to access helper function directly from your controllers view_context.helper_name
You can include your helper methods into a controller with a helper keyword syntax
class MyController < ApplicationController
helper ApplicationHelper
end

Rails - Two controllers or adding actions?

Designing a web app with a admin section and a public facing section. It feels like having a public facing controller just for "index" and "show" is a bit redundant. All the suggestions I've read suggest a namespace for admin, which is fine. I just wonder if I should have one controller with an addition action, say "list_public" or something like that.
I'm new with Rails, so maybe I'm just concerned about nothing. I just don't like the idea of having all these controllers, views, helpers with the same name scattered all over my project directories.
Anyone have any insight to this? Thanks in advance.
I would say having both controllers (one public, and one admin) is the best solution.
Now what you could do is have both the controllers call the same method that does the related actions in the actions.
class MyController < ApplicationController
def show
MyModel.do_all_sorts_of_stuff
end
end
class Admin::MyController < ApplicationController
def show
MyModel.do_all_sorts_of_stuff
# Admin only stuff goes here
end
end
As Matt said, but you can also do this:
class MyController < ApplicationController
def show
MyModel.do_all_sorts_of_stuff
end
end
class Admin::MyController < MyController
def show
super
# Admin only stuff goes here
end
end
This means that you can just focus on the more specialised cases for Admin::MyController rather than repeating code.

Resources