Мне нужно вызвать действие create в контроллере A из контроллера B.
Причина в том, что мне нужно перенаправить иначе, когда я звоню с контроллера B.
Можно ли это сделать в Rails?
Мне нужно вызвать действие create в контроллере A из контроллера B.
Причина в том, что мне нужно перенаправить иначе, когда я звоню с контроллера B.
Можно ли это сделать в Rails?
Ответы:
Вы можете использовать перенаправление на это действие:
redirect_to your_controller_action_url
Подробнее: Руководство по Rails
Чтобы просто отобразить новое действие:
redirect_to your_controller_action_url and return
renderвместо redirect_to. Что скажешь, @Spyros?
redirect_toне позволяет использовать, post: :methodи это может быть полезно, в частности, для перенаправления на уже существующее createдействие другого контроллера, как @ddayan спросил в первый раз. У меня похожая ситуация, когда в какой-то ситуации я должен создать другой объект. Вызов другого createдействия может быть DRYer ..
Чтобы использовать один контроллер от другого, сделайте следующее:
def action_that_calls_one_from_another_controller
controller_you_want = ControllerYouWant.new
controller_you_want.request = request
controller_you_want.response = response
controller_you_want.action_you_want
end
controller_you_wantвы бы это сделалиcontroller_you_want.process(:action_you_want)
render status: :ok, json: JSON.parse(controller.render(:action_you_want).first)похоже, работает, чтобы вернуть JSON от другого контроллера
controller_you_want.requestно не смогли получить этот запуск с передачей хэша или экземпляра параметров.
paramsстановятся доступными controller_you_want, установив requestв 3-й строке. Вы об этом спрашиваете?
render html: controller_you_want.process(:action_you_want)
Представленная вами логика не совместима с MVC и не с Rails.
Контроллер отображает представление или перенаправление
Метод выполняет код
Исходя из этих соображений, я советую вам создавать методы в вашем контроллере и вызывать их из вашего действия.
Пример:
def index
get_variable
end
private
def get_variable
@var = Var.all
end
Тем не менее, вы можете делать то же самое через разные контроллеры и вызывать метод из контроллера A, пока вы находитесь в контроллере B.
Словарь очень важен, поэтому я очень настаиваю.
get_variableтеперь можно вызвать с другого контроллера?
Вы можете использовать url_forдля получения URL-адреса контроллера и действия, а затем использовать redirect_toдля перехода по этому URL-адресу.
redirect_to url_for(:controller => :controller_name, :action => :action_name)
redirect_to url_for(:controller => :controller_name, :action => :action_name, :param1 => :val1, :param2 => :val2)будет результат /contorller_name/action_name?param1=val1¶m2=val2. См. Документацию
Это плохая практика - вызывать другое действие контроллера.
Вам следует
Мое мнение:
Третий подход - это то, что я делал часто. Я покажу небольшой пример.
def create
@my_obj = MyModel.new(params[:my_model])
if @my_obj.save
redirect_to params[:redirect_to] || some_default_path
end
endТаким образом, вы можете отправить в этот параметр действия redirect_to, который может быть любым путем.
/modelsили обычный класс или модуль в /lib). Единственная проблема заключается в том, что ваш контроллер взаимодействует с представлением через переменные экземпляра - вам придется исправить это дублирование другим способом.
Может быть, логику можно было бы извлечь в помощника? помощники доступны всем классам и не передают управление. Вы можете проверить в нем, возможно, имя контроллера, чтобы узнать, как он был вызван.
Композиция на помощь!
Учитывая причину, вместо того, чтобы вызывать действия между контроллерами, следует разрабатывать контроллеры для разделения общих и настраиваемых частей кода. Это поможет избежать как дублирования кода, так и нарушения паттерна MVC.
Хотя это можно сделать разными способами, использование проблем ( композиции ) является хорошей практикой.
# controllers/a_controller.rb
class AController < ApplicationController
include Createable
private def redirect_url
'one/url'
end
end
# controllers/b_controller.rb
class BController < ApplicationController
include Createable
private def redirect_url
'another/url'
end
end
# controllers/concerns/createable.rb
module Createable
def create
do_usefull_things
redirect_to redirect_url
end
end
Надеюсь, это поможет.
Отделите эти функции от контроллеров и поместите их в файл модели. Затем включите файл модели в свой контроллер.