Ну, прежде всего, полностью ли протестирован этот код, включая все мириады условий? Это настолько сложно, что рефакторинг наверняка будет катастрофическим, если набор тестов не будет строгим. Итак, напишите комплексный набор тестов, если у вас его еще нет. Если уже существует набор тестов, убедитесь, что он проверяет все условия.
Во-вторых, примените парадигму «толстая модель и тощий контроллер». Итак, перенесите всю сложность в модель, назовем ее CompanyFilter
def index
companies_list = CompanyFilter.new(current_user, params).list
response = { data: companies_list.alphabetical.as_json(current_user: current_user) }
json_response(response)
end
и переместим все эти операторы if / then / else в метод CompanyFilter#list
тесты все еще проходят? отлично, вы все равно будете получать предупреждения Rubocop, но относящиеся к классу CompanyFilter.
Теперь вам нужно распутать все условия. Мне немного сложно понять, что происходит, но похоже, что это должно быть сведено к одному оператору case с 5 возможными результатами. Итак, класс CompanyFilter может выглядеть примерно так:
class CompanyFilter
attr_accessors :current_user, :params
def initialize(current_user, params)
@current_user = current_user
@params = params
end
def list
case
when no_filter_specified
{}
when user_is_admin
@current_user.admin_companies
when user_is_owned
# etc
when # other condition
# etc
end
end
private
def no_filter_specified
@params[:filter].blank?
end
def user_is_admin
# returns boolean based on params hash
end
def user_is_owned
# returns boolean based on params hash
end
end
тесты все еще проходят? идеальный! [Edit] Теперь вы можете перенести большинство тестов вашего контроллера в модельный тест для класса CompanyFilter.
Наконец, я бы определил все различные запросы companies_list как области на модели компании, например
class Company < ApplicationRecord
# some examples, I don't know what's appropriate in this app
scope :for_user, ->(user){ where("...") }
scope :administered_by, ->(user){ where("...") }
end