Где ставить только вспомогательные методы для контроллеров?
Я хочу написать определенные методы обработки строк и другие задачи, которые выполняются во многих моих контроллерах. Я знаю, что его плохая практика заключается в включении помощников в ваш контроллер, поэтому мне просто интересно, где лучшее место для применения широкого спектра приложений, используемых в контроллерах?
Я понимаю, что некоторые из вас скажут, чтобы помещать их в модели, но вы должны понимать, что не все мои контроллеры имеют связанную модель. Будет оценен любой вход.
Ответы
Ответ 1
Если вам нужно использовать метод в области приложения, я бы предположил, что вы храните эти методы внутри контроллера приложения и чтобы использовать их внутри представлений.. объявите их как вспомогательные методы.
Например,
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
Ответ 2
Я стараюсь помещать их в помощников. Тот факт, что они включены в представления
автоматически не было проблемой для меня. Вы также можете разместить их в
что-то вроде приложения/проблем/или lib/
Мне не нравится загромождать ApplicationController с частными методами
потому что это часто становится беспорядком.
Пример:
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
Ответ 3
Я бы предложил разместить их в папке lib
. Так, например, у меня есть:
lib/utils/string_utils
module StringUtils
def foo
...
end
end
class BarController < ActionController::Base
include StringUtils
end
Это демонстрирует хорошую методологию под названием Fat model, Thin controller. В этом случае мы используем Mixins вместо моделей для разделения логики, но идея такая же. Вы хотите, чтобы ваши контроллеры были как можно более простыми.
Ответ 4
Все зависит от ваших потребностей. Я приведу здесь 2 примера. Оба они представляют собой только пользовательские библиотеки, расположенные в каталоге lib
.
Первый пример - "обработка пользовательских строк"
# 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
Второй пример - помощник для флэш-сообщений
# 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
Примечание. Не забудьте добавить lib
dir в пути автозагрузки. В config/application.rb
добавить/изменить эту строку config.autoload_paths += %W(#{config.root}/lib)
.
Поэтому для меня ответ - lib
.
Ответ 5
Если эти методы используются в многочисленных контроллерах, я бы определил их в application_controller.rb
. Каждый контроллер будет наследовать от него и сможет использовать любой метод, определенный там.
Ответ 6
Начиная с Rails 4 для него есть выделенная папка app/controllers/concerns
. Таким образом, вы можете создать модуль там, а затем включить его в определенный контроллер или в ApplicationController, если он вам понадобится на всех ваших контроллерах.