Muszę wywołać akcję tworzenia w kontrolerze A, z kontrolera B.
Powodem jest to, że muszę przekierować inaczej, gdy dzwonię z kontrolera B.
Czy można to zrobić w Railsach?
Muszę wywołać akcję tworzenia w kontrolerze A, z kontrolera B.
Powodem jest to, że muszę przekierować inaczej, gdy dzwonię z kontrolera B.
Czy można to zrobić w Railsach?
Odpowiedzi:
Możesz użyć przekierowania do tej akcji:
redirect_to your_controller_action_url
Więcej na: Przewodnik po Railsach
Aby po prostu wyrenderować nową akcję:
redirect_to your_controller_action_url and return
render
zamiast redirect_to
. Co powiesz, @Spyros?
redirect_to
nie pozwala na użycie post: :method
i może to być przydatne szczególnie w przypadku przekierowania do już istniejącej create
akcji innego kontrolera, o co @ddayan zapytał za pierwszym razem. Mam podobną sytuację, w której w jakiejś sytuacji powinienem stworzyć kolejny obiekt. Wywołanie drugiej create
akcji może być DRYer ..
Aby użyć jednego kontrolera od innego, wykonaj następujące czynności:
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
, zrobiłbyś tocontroller_you_want.process(:action_you_want)
render status: :ok, json: JSON.parse(controller.render(:action_you_want).first)
wydaje się działać, aby zwrócić JSON z innego kontrolera
controller_you_want.request
ale nie udało się uzyskać tego odpalenia, przekazując instancję skrótu lub parametrów.
params
się dostępne controller_you_want
, ustawiając request
w trzeciej linii. Czy o to pytasz?
render html: controller_you_want.process(:action_you_want)
Logika, którą prezentujesz, nie jest zgodna z MVC, a następnie z Railsami.
Kontroler renderuje widok lub przekierowuje
Metoda wykonuje kod
Na podstawie tych rozważań radzę utworzyć metody w kontrolerze i wywołać je z akcji.
Przykład:
def index
get_variable
end
private
def get_variable
@var = Var.all
end
To powiedziawszy, możesz zrobić dokładnie to samo za pomocą różnych kontrolerów i przywołać metodę z kontrolera A, gdy jesteś w kontrolerze B.
Słownictwo jest niezwykle ważne, dlatego bardzo nalegam.
get_variable
teraz wywołać z innego kontrolera?
Możesz użyć, url_for
aby uzyskać adres URL kontrolera i akcji, a następnie użyć, redirect_to
aby przejść do tego adresu 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)
spowoduje /contorller_name/action_name?param1=val1¶m2=val2
. Zobacz dokumentację
Wywoływanie innej akcji kontrolera jest złą praktyką.
Powinieneś
Moja opinia:
Trzecie podejście jest tym, co często robiłem. Więc pokażę mały przykład.
def create
@my_obj = MyModel.new(params[:my_model])
if @my_obj.save
redirect_to params[:redirect_to] || some_default_path
end
end
Możesz więc wysłać do tego redirect_to
parametru akcji , którym może być dowolna ścieżka.
/models
lub zwykłej klasy lub modułu w /lib
). Jedynym problemem jest to, że kontroler komunikuje się z widokiem za pośrednictwem zmiennych instancji - musisz naprawić tę duplikację w inny sposób.
Może logikę można by wydobyć z pomocnika? pomocnicy są dostępni dla wszystkich klas i nie przekazują kontroli. Możesz sprawdzić w nim, być może nazwę kontrolera, aby zobaczyć, jak został wywołany.
Kompozycja na ratunek!
Biorąc pod uwagę przyczynę, zamiast wywoływać akcje między kontrolerami, należy zaprojektować kontrolery, aby oddzielić wspólne i niestandardowe części kodu. Pomoże to uniknąć zarówno duplikowania kodu, jak i łamania wzorca MVC.
Chociaż można to zrobić na wiele sposobów, dobrą praktyką jest stosowanie obaw ( składu ).
# 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
Mam nadzieję, że to pomoże.
Oddziel te funkcje od kontrolerów i umieść je w pliku modelu. Następnie dołącz plik modelu do kontrolera.