Reputation: 2139
I am looking to write certain methods for processing strings, and other tasks that take place in numerous of my controllers. I know its bad practice to include helpers in your controller, so I was just wondering, where is the best place to put application wide methods used in controllers?
I realize some of you will say to put them in models, but you have to realize that not all my controllers have an associated model. Any and all input would be appreciated.
Upvotes: 21
Views: 11913
Reputation: 787
Starting from Rails 4 there is a dedicated folder for it app/controllers/concerns
. So you can create a module there and then include it in a specific controller(s) or in ApplicationController if you need it available throughout all your controllers.
Upvotes: 1
Reputation: 7733
If you need to use a method in the application scope then I would suggest that you keep those methods inside the application controller and in order to use them inside views.. declare those as helper methods.
For example,
class ApplicationController < ActionController::Base
helper_method :current_user, :some_method
def current_user
@user ||= User.find_by_id(session[:user_id])
end
def some_method
end
end
Upvotes: 11
Reputation: 15276
I would suggest to put them in lib
folder. So for example I have:
lib/utils/string_utils
module StringUtils
def foo
...
end
end
class BarController < ActionController::Base
include StringUtils
end
This demonstrates good methodology called Fat model, Thin controller, in this case we are using Mixins instead of Models to separate logic but idea is same. You want your controllers as simple as possible.
Upvotes: 9
Reputation: 1888
It all depends on your needs. I will provide here 2 examples. Both of them are just a custom libraries, located under lib
directory.
First example - "custom string processing"
# lib/filters.rb
module Filters
# Converts value to canonical view
def self.phone(value)
# remove all non-digits
clean_value = value.gsub(/\D/, '')
country_codes = configus.phone.country_codes
area_code = configus.phone.defaults.area_code
case clean_value.length
when 7
"#{area_code}#{clean_value}"
when 11
# remove country code only if phone starts with the allowed country code
if country_codes.include?(clean_value[0].to_i)
clean_value[1..-1]
else
clean_value
end
else clean_value
end
end
# usage
# app/api/phones_controller.rb
class Api::PhonesController < Api::ApplicationController
def exists
if params[:q]
clean_value = Filters.phone(params[:q])
...
end
end
end
Second example - helper for flash messages
# lib/flash_helper.rb
module FlashHelper
def flash_translate(key, options = {})
scope = [:flash, :controllers]
scope += params[:controller].split('/')
scope << params[:action]
t(key, {:scope => scope}.merge(options))
end
end
# app/application_controller.rb
class ApplicationController < ActionController::Base
include FlashHelper
end
# usage
# app/your_controller.rb
class YourController < ApplicationController
def create
@object = Object.new(params[:object])
if @object.save
flash[:success] = flash_translate(:success)
...
end
end
end
Note: do not forget to add lib
dir to the autoload paths. In config/application.rb
add/modify this line config.autoload_paths += %W(#{config.root}/lib)
.
So for me the answer is lib
directory.
Upvotes: 3
Reputation: 20639
I tend to put them into helpers. The fact that they are included in views automatically haven't been a problem for me. You can also place them into something like app/concerns/ or lib/
I don't like cluttering ApplicationController with private methods because this often becomes a mess.
Example:
module AuthenticationHelper
def current_user
@current_user # ||= ...
end
def authenticate!
redirect_to new_session_url unless current_user.signed_in?
end
end
module MobileSubdomain
def self.included(controller)
controller.before_filter :set_mobile_format
end
def set_mobile_format
request.format = :mobile if request.subdomain == "m"
end
end
class ApplicationController
include AuthenticationHelper
include MobileSubdomain
end
Upvotes: 13
Reputation: 6371
In case those methods are used in numerous controllers, I would define them in application_controller.rb
. Every controller will inherits from it and will be capable to use any method defined there
Upvotes: 0