Page 112 of 165

Rails3 + mały middleware z kontrolerem

Ostatnimi dniami wzięło mnie na poprawianie moich repo na githubie. Jednym z pluginów do poprawy był mój niewielki Custom Errors Handler, który ma za zadanie generować odpowiedni szablon błędu zależnie od miejsca w którym wystąpił błąd. Dzięki temu, np. moduł administracji może mieć inne 404 niż moduł użytkowników.

Cały kod składa się z dwóch klas:

  • MyActionDispatch::ShowExceptions
  • CustomErrorsHandlerController

Pierwsza z nich to middleware odpowiedzialny za przejmowanie obsługi wyświetlania wyjątków, drugi to kontroler który ma wygenerować widok.

W cały kod wgłębiać się nie będę (jest dostępny na moim githubie), opiszę jednak proces dodawania middlewaru z poziomu gemu dedykowanego dla Railsów. Dawniej był plik init.rb, w którym można było najzwyczajniej nadpisać domyślny ActionDispatch::ShowExceptions. Takie podejście w Railsach3 jednak nie przejdzie (chociaż póki co, jako plugin działa ;) ). Aby móc nasz middleware wykorzystać zamiast domyślnego, posłużymy się metodą swap middleware'u (o innym metodach z rodziny middleware'u przeczytasz tutaj).

Zamiana jest całkiem prosta:

  class Railtie < Rails::Railtie
    initializer "app.insert_my_errors_handler" do |app|
      app.config.middleware.swap ActionDispatch::ShowExceptions, 
        MyActionDispatch::ShowExceptions
    end
  end

Podajemy co zamieniamy i na co, pamiętając przy tym, że init.rb już nie jest wywoływany, więc ten kod powinien trafić do /lib/nazwa_gema.rb.

Pamiętajmy też, że jeżeli chcemy mieć kompletnie niezależny kontroler - nie powinien on dziedziczyć po ApplicationControlerze, ale raczej bezpośrednio po ActionController::Base, dzięki czemu nie będzie zależny od filtrów nałożonych na ApplicationController.

Odpalanie wielu serwerów z pomocą jednego polecenia

Trafiają się nam projekty, w których wymagane jest uruchamianie kilku (kilkunastu) usług zanim będziemy mogli pracować. Odpalanie tego (i zarządzanie) w kilku oknach jest delikatnie mówiąc niewygodne.

Aby sobie to ułatwić, wystarczy napisać prosty skrypt w Bashu, który dane serwery będzie odpalał bezpośrednio w screenie. Ostatni z odpalanych serwerów pozostawimy "na wierzchu", dopisując kod który w momencie naciśnięcia na nim Ctrl+C (zamknij), wyłączy wszystkie pozostałe serwery. W ten sposób będziemy mogli łatwo i wygodnie zarządzać uruchamianiem i zamykaniem całego projektu. Dodamy sobie także alias tak, aby móc wygodnie wywoływać nasz skrypt.

Załóżmy, że nasz projekt nazywa się Kotowari. Wszystkie tworzone (później) screeny będą zawierać w sobie tę nazwę. Dzięki temu, będziemy mogli je zabić pozostawiając inne pracujące screeny (nie związane z projektem). Zdefiniujemy sobie także pułapkę na Ctrl+C:

trap close_screens INT

function close_screens() {
	kill -9 `ps aux  | awk '/Kotowari/{print $2}'`
	screen -wipe
}

Teraz pora na odpalanie kolejnych serwerów. Serwery które odpalamy przez init.d lub takie które nie potrzebują do pracy konsoli (nie "zostają" w niej), możemy odpalać bezpośrednio czyli:

sudo /etc/init.d/apache2 start;
sudo /etc/init.d/mysql start;

Warto zwrócic uwagę, że nie zostaną one zabite podczas zamykania projektu. Dlaczego to tak zostawiam? Tego typu procesy i tak zazwyczaj chodzą niezależnie od danego projektu i są współdzielone (zazwyczaj są też włączane przy boocie systemu - próbujemy je włączyć tak dla pewności). Oczywiście nic nie stoi na przeszkodzie aby je zamykać w napisanej powyżej funkcji close_screens().

Teraz pora na procesy dedykowane naszej aplikacji i zamknięcie całości:

screen -d -S "Kotowari Proc 1" -m "/sciezka/do/naszego/procesu1"
screen -d -S "Kotowari Proc 2" -m "/sciezka/do/naszego/procesu2"

"/sciezka/do/naszego/procesu3"

close_screens

Ostatni proces nie jest uruchamiany w screenie, ponieważ on ma nam zostać "na" konsoli. Jego zamknięcie zainicjuje funkcję close_screens która zamknie resztę z procesów ukrytych w screenach.

Jeszcze tylko alias:

alias nasz_projekt="/sciezka/do/naszego/skryptu.sh"

Całość:

trap close_screens INT

function close_screens() {
	kill -9 `ps aux  | awk '/Kotowari/{print $2}'`
	screen -wipe
}

sudo /etc/init.d/apache2 start;
sudo /etc/init.d/mysql start;

screen -d -S "Kotowari Proc 1" -m "/sciezka/do/naszego/procesu1"
screen -d -S "Kotowari Proc 2" -m "/sciezka/do/naszego/procesu2"

"/sciezka/do/naszego/procesu3"

close_screens

Copyright © 2024 Closer to Code

Theme by Anders NorenUp ↑