Создать контроллер оболочки для всех вызовов веб-служб в рельсах

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

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

Код ниже

class EmployeeController < ApplicationController

  def list
  end

end


class DepartmentController < ApplicationController

  def list
  end

end

конечная точка будет http://localhost:3000/employee/list & Амп; http://localhost:3000/department/list

Каков наилучший способ создать контроллер-оболочку и вызвать любое из действий контроллеров.

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

class WrapperController < ApplicationController


  def list
    if params["which"].eql?("employee")
      data = EmployeeController.new(params).create
    else
      data = DepartmentController.new(params).label
    end

  end
end

конечная точка будет http://localhost:3000/wrapper/list

Любая помощь будет оценена по достоинству. Спасибо заранее.

Ответ 1

Этот WrapperController звучит как очень плохая идея. Особенно создавая экземпляр другого контроллера и вызывая метод на нем. Я не помню, чтобы увидеть такой рисунок где угодно. Rails делает много волшебства вокруг цикла запроса/ответа, поэтому вызов другого контроллера, скорее всего, сломает что-то позже. Я просто предполагаю, что файлы cookie могут не работать, или рендеринг может быть поврежден и т.д.

В любом случае, что вы, вероятно, хотите, лучше организовать вашу бизнес-логику внутри приложения Rails. В качестве отправной точки я настоятельно рекомендую прочитать эту статью. Основываясь на ограниченной информации из вашего вопроса, трудно дать хороший ответ для вашего конкретного случая.

Например, вы можете реализовать объект запроса:

class EmployeesQuery
  def initialize(params)
    # initialize some internal variables
  end

  def list
    # write code for fetching employees based on passed params
  end
end

class DepartmentsQuery
  def initialize(params)
    # initialize some internal variables
  end

  def list
    # write code for fetching employees based on passed params
  end
end

class QueryFactory
  QUERIES = {
    "employee" => EmployeeQuery,
    "department" => DepartmentQuery
  }

  get self.get_query(resource)
    QUERIES[resource] || raise("Some exception")
  end
end

Теперь вы можете создать ListsController:

class ListsController < ApplicationController
  def index
    data = QueryFactory.get_query(params[:which]).list
    # render specific view based on requested resource
    # and rescue possible exception from get_query method
  end
end

И в config/routes.rb:

get "/:which/list" => "lists#index"

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

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

Также вы можете решить свою проблему гораздо проще, просто изменив config/routes.rb немного.

get "/:controller/list", to: :list

Он направит /employee/list до EmployeeController и /department/list в DepartmentController. И в основном это направит на любой действительный контроллер, поэтому, возможно, вы захотите немного его настроить и добавить некоторые ограничения.

Надеюсь, что это поможет. Приветствия.

Ответ 2

Почему мы не должны просто пересылать его с тем же запросом

class WrapperController < ApplicationController


  def list
    if params["which"].eql?("employee")
      controller = EmployeeController.new
    else
      controller = DepartmentController.new
    end
    controller.request = request
    controller.response = response
    controller.list

  end
end

Ответ 3

У вас уже есть это с Application Controller, поэтому его родительский контроллер. Стандартный способ заключается в добавлении before_action в ApplicationController, который выполняет проверку, а затем перенаправляет на правильный контроллер.

class ApplicationController

    before_action :check_emp_or_dept

    def check_emp_or_dept
        if employee_params.fetch("which", "").eql?("employee")
            @employee = Employee.find employee_params['id'] 
            redirect_to @employee
        else
            @department = Department.find department_params['id']
            redirect_to @department
        end
    end

  protected
    # handle strong params according to what your model requires
    def department_params
      params.require(:department).permit(:param1, :param2)
    end

    # handle strong params according to what your model requires
    def employee_params
        params.require(:department).permit(:param1, :param2)
    end

end

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

Ответ 4

Вы можете сделать это легко в маршрутизации (т.е. routes.rb файл) с помощью ограничений:

get '/wrapper/list', to: 'employee#list', 
  constraints: lambda { |request| 
    request.query_parameters["which"] == "employee"
  }
get '/wrapper/list', to: 'department#list', 
  constraints: lambda { |request|
    request.query_parameters["which"] != "employee"
  }