Идея шаблона проектирования контроллера Rails для уменьшения его размера - PullRequest
0 голосов
/ 21 октября 2018

Вопрос в том, что вы думаете об этом шаблоне?

Проблема: у вас есть контроллер с действием индекса, и это действие огромно.Действие полно цепочек ActiveRecord и, возможно, некоторых вычислений с записями.Когда вы добавляете новые методы, контроллер становится больше.

Я слышал о "тощей модели контроллера с толстыми токами", и я только что?Мои модели уже толстые, вы с ума сошли?

Я слышал об объектах обслуживания, они не очень удобны для меня.

result = SomeService.new(params, request, flash, current_user).call

После такого объекта обслуживания вы можете попробовать:

result = SomeService.new(controller).call
# or
result = SomeService.new.(controller)

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

Вот шаблон из темы:

# controllers/some_controller.rb
class SomeController < OtherController
  before_actions

  include Index
  include Show

  def create_update_and_destroy
    # small methods have no reason to leave controller
  end

  private

  def common_private_method
  end
end

# controllers/some_controller/index.rb
module SomeController::Index
  def index
    # code here
  end

  private

  def index_do_some_stuff
    # this method is prefixed by "index" to avoid name collision
  end
end

Да, есть some_controllerКаталог .rb и some_controller с действиями в виде файлов.

Никто в ООП не любит префиксы, и если ваш метод хорошо объясняет не короткое имя - префикс не нужен.

На мой взгляд, этоСамый простой и очевидный способ.Просто возьми жирный код и разбей на модули!Как вы думаете?

Объяснения того, почему у меня много кода:

В одном проекте, который у меня есть, требуются записи из нескольких моделей, некоторые связанные, некоторые не связанные.

Итак, я начал писать много областей в моделях, прошло время, и я понял, что это неправильный подход.

Различные действия требовали очень конкретного выбора записей, только действие должно знать о таких особенностях.И у меня были области с именами «for_index», «for_show».

Теперь я создаю модуль Index с индексом метода, и весь выбор записи и вычислительный код разбивается на частные методы прямо на месте.

В другом проекте у меня есть API.Конкретная конечная точка возвращает определенный глубоко вложенный JSON, несколько моделей выбираются.Я уже знаю, что создание областей в модели для одной конкретной конечной точки - плохая идея, поэтому я делю код на частные методы.Одно действие и пять частных методов для него.А следующие пять публичных методов и 25 приватных?В одном контроллере?

1 Ответ

0 голосов
/ 21 октября 2018

Сочетание form objects с service objects и другими шаблонами может сделать вашу модель и контроллер тонкими.Вы также можете добавить объект ActiveResource::Errors в объект службы для сбора ошибок.

Вот пример использования ввода пользователя.Настройте его в соответствии со своей спецификацией

class ProductForm
  ...
  def save
    if service_object.call
      self
    else
      append_errors(service_object)
      false
    end
  end

  def service_object
    @service_object ||= ProductCreationService.new(params)
  end

  def append_errors object
    errors.append object.errors # just for simplicity
  end
end

В вашем контроллере

def create
  @product = ProductForm.new params
  if @product.save
    ...
  else
    ...
  end
end

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

Действия, которые собирают данные, можно абстрагировать с помощью query / finder объектов.

Вот грубый пример

class DashboardQuery
  attr_reader :options
  def initalize(options = {})
    @options = options
  end

  def branches
    @branches ||= Branch.all
  end

  def branch_count
    @branch_count ||= branches.count
  end
end

# Usage
@dashboard = DashboardQuery.new(params)
@dashboard.branch_count
@dashabord.branches
...