, где нужно использовать только вспомогательные методы для контроллеров?

18

Я хочу написать определенные методы обработки строк и другие задачи, которые выполняются во многих моих контроллерах. Я знаю, что его плохая практика заключается в включении помощников в ваш контроллер, поэтому мне просто интересно, где лучшее место для применения широкого спектра приложений, используемых в контроллерах?

Я понимаю, что некоторые из вас скажут, чтобы помещать их в модели, но вы должны понимать, что не все мои контроллеры имеют связанную модель. Будет оценен любой вход.     

задан flyingarmadillo 14.08.2012 в 12:41
источник

6 ответов

10

Если вам нужно использовать метод в области приложения, я бы предположил, что вы храните эти методы внутри контроллера приложения и чтобы использовать их внутри представлений .. объявите их как вспомогательные методы.

Например,

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
    
ответ дан Sandip Ransing 14.08.2012 в 12:48
источник
  • Проблема заключается в том, что если есть много вспомогательных методов, ApplicationController может стать громоздким. Я предпочитаю разбить методы на вспомогательные файлы по категориям и включать файлы в ApplicationController, как это было предложено в ответе Семена Перепелицы. –  Teemu Leisti 09.09.2013 в 14:34
11

Я стараюсь помещать их в помощников. Тот факт, что они включены в представления автоматически не было проблемой для меня. Вы также можете разместить их в что-то вроде приложения / проблем / или 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
    
ответ дан Simon Perepelitsa 14.08.2012 в 13:07
источник
  • Это то, что я тоже делаю. –  Teemu Leisti 09.09.2013 в 14:32
  • Это имеет для меня больше смысла, чем заполнение каждого вспомогательного метода в Application Controller. –  dscher 18.06.2014 в 21:12
5

Я бы предложил разместить их в папке lib . Так, например, у меня есть:

lib/utils/string_utils

module StringUtils

  def foo
     ...
  end
end

class BarController < ActionController::Base
  include StringUtils
end

Это демонстрирует хорошую методологию под названием Fat model, Thin controller . В этом случае мы используем Mixins вместо моделей для разделения логики, но идея такая же. Вы хотите, чтобы ваши контроллеры были как можно более простыми.

    
ответ дан Haris Krajina 14.08.2012 в 13:53
источник
2

Все зависит от ваших потребностей. Я приведу здесь 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 .

    
ответ дан melekes 14.08.2012 в 20:12
источник
0

Если эти методы используются в многочисленных контроллерах, я бы определил их в application_controller.rb . Каждый контроллер будет наследовать от него и сможет использовать любой метод, определенный там.

    
ответ дан davids 14.08.2012 в 12:48
источник
0

Начиная с Rails 4 для него есть специальная папка app/controllers/concerns . Таким образом, вы можете создать модуль там, а затем включить его в определенный контроллер (ы) или в ApplicationController, если он вам понадобится на всех ваших контроллерах.

    
ответ дан Seybo Glaux 10.08.2017 в 10:04
источник