Создать контроллер оболочки для всех вызовов веб-служб в рельсах
Я работаю над созданием оболочки для существующих контроллеров приложений.
Например, у меня есть два контроллера, которые принимают одинаковый набор параметров и аналогичные методы.
Код ниже
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"
}