#Euruko2017 - Zapowiedź serii

Zapowiedź serii wideo z Euruko 2017 w Budapeszcie



Warsztaty Ruby on Rails z inFakt

Zapraszamy na Warsztaty z programowania Ruby on Rails, które rozpoczną się 8 listopada w Krakowie.



Druga edycja warsztatów

To już druga edycja serii spotkań zespołu IT inFaktu z developerami, którzy chcą rozwijać swoje umiejętności w budowaniu aplikacji webowych.

Zachęceni bardzo pozytywnymi opiniami po warsztatach dla początkujących programistów, przygotowaliśmy kolejny zestaw praktycznych ćwiczeń, które pozwolą zrobić kolejny krok w drodze do zostania railsowym wymiataczem.
Jeżeli masz już podstawowe doświadczenie w technologii Ruby on Rails i kilka prostych projektów za sobą, to jesteś idealnym kandydatem do tego, żeby wspólnie z nami rozszerzać swoje developerskie horyzonty!

Warsztaty Ruby on Rails z inFakt to trzy spotkania po ok. 3 godziny, w trakcie których uczestnicy będą budować i ulepszać prostą aplikację, wykorzystując świeżo zdobyte umiejętności. Obecni na sali mentorzy na każdym kroku będą oferować wsparcie merytoryczne, wyjaśniać ewentualne wątpliwości i udzielać dobrych rad, bazując na swoim doświadczeniu.

Czego się nauczysz?

W trakcie warsztatów, w praktyce poznasz i przećwiczysz tematy:

  • Kontrolery i widoki
  • Routing, modele, konfiguracja aplikacji
  • Testy i clean up aplikacji
  • Zadania w tle
  • API
  • Odciążanie bazy danych
  • Omniauth 2
  • Integracja z zewnętrzną usługą


Zapisy na warsztaty

Jeżeli czujesz, że takie spotkania mogą być dla Ciebie wartościowe - zachęcamy do zgłoszenia swojego udziału!

Formularz rejestracyjny dostępny jest na stronie www dedykowanej warsztatom: www.infakt.pl/warsztaty-rails.

Uwaga: Zgłoszenia uczestników przyjmujemy tylko do 29 października 2017r.

Zapraszamy!

Czym może zaskoczyć Cię case statement

Przesadziłabym mówiąc, że nie ma dnia, żebym pisząc w Rubym nie skorzystała z case’a. Wydawało mi się jednak, że znamy się już całkiem nieźle… aż pewnego razu okazało się, że właściwie „znamy sie tylko z widzenia”, bo nigdy nie zastanawiałam się nad tym jak działa pod maską.

Gdyby ktoś spytał mnie kiedyś jak należy rozumieć

case grade
when "A", "B"
  puts 'You’ve passed! Great!'
when "C", "D"
  puts 'You’ve passed… but...'
else
  puts 'You haven’t passed, sorry'
end

Odpowiedziałabym:

Jeżeli grade równa się A lub B - wpisz 'You’ve passed! Great!'. W przeciwnym razie, jeżeli jest równa C lub D - wypisz 'You’ve passed… but...'. W każdym innym przypadku wypisz 'You haven’t passed, sorry'.

Czy odpowiedziałabym poprawnie? Tak i nie.
Tak - ponieważ w tym przypadku do tego sprowadza się zapisana składnia i na tzw. „chłopski rozum” - tak właśnie zadziała.
Nie - ponieważ znaczyłoby to, że należałoby to przełożyć na zapis

if grade == "A" || grade == "B"
  puts 'You’ve passed! Great!'
elsif grade == "C" || grade == "D"
  puts 'You’ve passed… but...'
else
  puts 'You haven’t passed, sorry'
end

…a nie tak działa case!

Case equality, threequals

Mechanizm case opiera się o tzw. (zaskakująca nazwa) case-equality, czyli operator “===”, zwany również threequals Poprawny, przepisany zapis powyższego wywołania to

if "A" === grade || "B" === grade
  puts 'You’ve passed! Great!'
elsif "C" === grade || "D" === grade
  puts 'You’ve passed… but...'
else
  puts 'You haven’t passed, sorry'
end

Już na pierwszy rzut oka widać, że “wartości” znajdują się po przeciwnej stronie porównania niż zakladakałam… I kolejność ta, przy porównaniu za pomocą “===” ma znaczenie!
Jaka więc jest różnica pomiędzy “==” a “===” ?

== VS ===

W wielu przypadkach, threequals zachowa się tak jak “==”, porównując obiekty. Przy niektórych wywołaniach możemy jednak odczytać left_x === right_y jako pytanie _czy right_y można umieścić w pudełku left_x ?

Dlatego też, prawdę zwrócą wszystkie następujące wywołania:

Integer === 5             # zachowa się jak is_a?
(1..5) === 3              # include?
/test/ === 'myteststring' # =~, zwracając boolean

Fałszywe okażą się natomiast wszystkie te wywołania z zamienioną kolejnością argumentów. (Czy Integer można umieścić w pudełku 5?)

WARNING: instance class

Ciekawym przykładem, na którym łatwo jest się potknąć, jest sprawdzanie klasy danego obiektu.

obj = 'hello'
String === obj.class
#=> false
String === obj
#=> true

Dlaczego tak się dzieje? Ponieważ obj.class jest obiektem klasy Class nie String! Warto o tym pamiętać, gdyż jest to bardzo łatwy do popełnienia błąd, jeżeli używając case’a mamy z tyłu głowy „tradycyjne” porównanie - aż prosi się o użycie

def evaluate(obj)
  case obj.class
  when String
    obj.capitalize
  when Array
    obj.join.capitalize
  else
    'error'
  end
end

evaluate("my string")
#=> "error"
evaluate(["array", "of", "strings"])
#=> "error"

Poprawnym natomiast jest pominięcie wywołania metody .class na obiekcie

def evaluate(obj)
  case obj
  when String
    obj.capitalize
  when Array
    obj.join.capitalize
  else
    'error'
  end
end

evaluate("my string")
#=> "My string"
evaluate(["array", "of", "strings"])
#=> "Array of strings"

Podsumowanie

O czym warto w takim razie pomyśleć, pisząc kolejnego case'a?
Co w życiu zmieni nam === ?

Przede wszystkim należy pamiętać, że często, ale nie zawsze case equality zadziała jak ==.
Z drugiej strony, dzięki threequals mamy więcej możliwości niż przy tradycyjnym porównaniu wartości - możemy np. skorzystać z wyrażeń regularnych.

  case obj
  when /\d/
    "Object includes integers"
  when /^[a-zA-Z]*$/
    "Object contains only letters"
  else
    "Other"
  end
end

2017: Aplikacja webowa

Praca ksiegowych zbyt często polega na żmudnym przepisywaniu kwot, numerków, dziesiątek tabelek z liczbami. Mamy zamiar to zmienić. Tworzymy arbitrue — wirtualnego asystenta księgowego, nowy produkt skierowany na rynek w Wielkiej Brytanii.

Jako zespół infakt.pl — od lat pomagamy małym przedsiębiorcom z całej Polski przy fakturowaniu i księgowości. Na nasz sukces składa się wiele czynników, ale wiemy, że jednym z nich jest dobrze zaprojektowana, intuicyjna i przejrzysta aplikacja webowa.

Stojąc przed nowym projektem, postawiliśmy sobie poprzeczkę jeszcze wyżej. W 2007 roku, gdy startowaliśmy z inFakt, postawiliśmy na Ruby on Rails. Dziś wiemy, że podjęliśmy dobrą decyzję. 10 lat później, w 2017 tworzymy nową aplikację i stajemy przed kolejnym wyborem. Chcemy móc za 10 lat powiedzieć to samo.

alt text

Nowa aplikacja webowa w 2017,

Nie trzeba być bacznym obserwatorem, aby stwierdzić, że przez ostatnie lata wiele się dzieje w świecie frontendu. Kiedyś wystarczyło generowanie widoków stron na serwerze. Potem, zaczęto modyfikować stronę (DOM) po stronie przeglądarki co spowodowało pojawienie się jQuery, następnie wprowadziliśmy się asynchroniczność za sprawą AJAX… pewnie znacie tą historię. W dalszej kolejności, zapragnęliśmy informować użytkownika na żywo o nowych zdarzeniach, np. wiadomościach, aktualizacjach, czy też zaksięgowanych plikach, np przy użyciu Web Socketów. Naturalnie wykształciła się koncepcja Single Page Application — SPA.

a więc Progressive Web Application,

W związku z rozwojem urządzeń mobilnych, sieci społecznościowych, chęci ujednolicenia wyglądu na różnych platformach, ukuto nową listę zasad: Progressive Web Application. Dziś, czy nam się to podoba czy nie, najlepsi tworzą aplikację które są:

  • Progresywne — Działają dla każdego, niezależnie od przeglądarki, ciągle dodając wsparcie dla nowych technologii, ponieważ jest tworzona z myślą o ciągłym rozwoju.
  • Responsywne — Działają na wszystkim. Komputerach, telefonach, tabletach, a nawet lodówkach, jeśli tylko jest dla nich zastosowanie.
  • Niezależne od jakości łącza — Dzięki serwisom działającym w tle, które potrafią wstrzymać wysyłanie danych aż do przywrócenia łączności, pozwalają na pracę offline i użytkownik nie odczuje, że pracuje na wolnym łączu.
  • ‘Aplikacyjne/natywne’ — Wyglądają i działają jak aplikacja, dzięki separacji funkcjonalności, od zawartości.
  • Aktualne — Zawsze zaktualizowane do najnowszej wersji, np. podczas cichych aktualizacji wykonywanych przez ‘service worker’.
  • Bezpieczne — Zawsze dostępne przez https.
  • Wykrywalne — Rozpoznawalne jako ‘aplikacja’, dzięki obecności W3C manifest i rejestracji w tle, przez co są obecne w wynikach wyszukiwania.
  • Ciągle zachęcające — Wysyłają np. wiadomości PUSH czy maile.
  • Instalowalne — Pozwalają na dodawawanie do pulpitu, bez ściągnięcia ze sklepu czy strony.
  • Pozwalające na linkowanie — Są dostępne pod linkiem nie wymagającym instalacji, który można łatwo udostępnić.

Tworzenie takich aplikacji przenosi dużą ilość logiki, ciężar tworzenia intefrejsu użytkownika z serwera na przeglądarkę, która z silnika do interpretacji wyglądu stron staje się pełną platformą uruchomieniową. Taka zmiana stwarza wiele wyzwań, dla projektantów, developerów jak i samych przeglądarek. Aby ułatwić tworzenie takich aplikacji, jak grzyby po deszczu wyrosło kilka rozwiązań w postaci frameworków. Doświadczenie nas nauczyło, że jeżeli chcemy być konkurencyjni, musimy wybierać zawsze najnowszą technologię. Biorąc pod uwagę trendy oraz to, że z punktu widzenia użytkownika aplikacje typu SPA mają niezaprzeczalnie lepszą użyteczność oraz szybkość — a to wartości, do których zawsze dążymy. Chcemy aby arbiture powtórzył sukces inFakt. Wiemy, że design i wybór technologii frontowej są kluczowe, aby zaskarbić sobie serca użytkowników. Ale jak ją wybrać?

działająca z REST API

W inFakt mamy doświadczenie w tworzeniu backendu oraz REST API w Ruby on Rails. Jesteśmy zadowoleni z tej technologii, pracują z nami eksperci i jesteśmy zaangażowani w działanie lokalnej społeczności Ruby. Postanowiliśmy pozostać przy niej, dlatego podstawowym warunkiem, który musi spełniać technologia w której stworzymy aplikację frontową jest wygodna wpółpraca z REST API i Ruby on Rails.

i WebSocketami

Aby zapewnić użytkownikowi ciągłe aktualizacje o nowych wiadomościach, powiadomieniach zdecydowaliśmy, że arbitrue będzie korzystać z WebSocketów. Ruby wspiera tą technologię, w oparciu o gem ActionCable. Znamy tą technologię i chcielibyśmy mieć możliwość jej użycia w naszej aplikacji frontowej.

oparta o bibliotekę…

Samobójstwem dla małego zespołu wydaje się być pisanie takiej aplikacji od zera, bez wsparcia żadnej biblioteki. Odpowiednie dobranie i wykorzystane frameworka, umożliwia szybkie tworzenie nowoczesnych aplikacji i daje możliwość efektywnej realizacji projektu. Mechanizmy, komponenty, pluginy, które można wykorzystać w aplikacji poprawiają przezjrzystość kodu, umożliwiają jego łatwe wielokrotne wykorzystanie. Działając zgodnie z konwencją proponowaną przez bibliotekę, piszemy kod który jest bardziej uporządkowany, przyjazny. Z drugiej strony, często frameworki mocno narzucają architekturę i sposób pisania aplikacji, która nie zawsze może wpisywać się w naszą wizję produktu. Wybierając bibliotekę przywiązujemy się nie tylko do technologii, ale także do ekosystemu, składającego się z wtyczek, tutoriali, przykładów i wsparcia. Aby ten wybór był możliwie świadomy, postanowiliśmy porównać trzy najpopularniejsze obecnie frameworki frontowe. Pierwszym działaniem było zawężenie listy kandydatów. W tym celu skorzystaliśmy ze strony stateofjs.com:

alt text

Niebieskia część słupka odpowiada za zainteresowanie technologią, czerwona doświadczeniami. Mniej nasycone kolory oznaczają brak zainteresowania, bądź złe doświadczenia, a nasycone żywe zainteresowanie bądź pozytywne doświadczenia. Wg danych, największe zainteresowanie wzbudzał Angular 2, Vue oraz React. Najwięcej satysfakcji przyniósł React (53/5) oraz Vue (10/1). Jako, że Angularjs(1) został zastąpiony Angularem 2, którego rozwinięciem jest Angular 4, pozostaniemy przy porównaniu z najnowszą wersją. Takie wyniki pozwoliły nam na szybkie zawężenie kandydatów do: React.js, Vue.js oraz Angular 2 (4)

Już niedługo opublikujemy bardziej techniczny artykuł porównujący te technologie.

Przekazywanie zmiennych w playbookach Ansible

Czasami problemem w playbookach Ansible staje się przekazywanie zmiennych między częściami tego playbooka wykonywanymi na różnych hostach. Rozważmy taki przypadek, w którym wykonamy następujące kroki:

  • Na lokalnej maszynie wykonamy przykładowe polecenie i zarejestrujemy jego wynik jako zmienną testvar
  • Połączymy się z innym hostem i spróbujemy odwołać się na nim do zmiennej testvar za pomocą modułu debug
  • Spróbujemy zmodyfikować przykładowy playbook tak, żeby zawartość zmiennej prawidłowo uzyskać.

Prosty playbook, który pozwoli nam na przetestowanie dostępności zmiennych wygląda np. tak:

---
- hosts: localhost
  become: no
  connection: local

  tasks:
  - shell: echo "Foo bar"
    register: testvar

  - debug: var=testvar

- hosts: vagrant.local
  become: no

  tasks:
  - debug: var=testvar

W efekcie wywołania takiego playbooka przekonamy się, że zmienna testvar, prawidłowo zarejestrowana na maszynie lokalnej, na hoście vagrant.local nie jest dostępna:

$ ansible-playbook -i 'vagrant.local,' test.local

PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [command] *****************************************************************
changed: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "testvar": {
        "changed": true,
        "cmd": "echo \"Foo bar\"",
        "delta": "0:00:00.001634",
        "end": "2017-03-17 16:58:20.821949",
        "rc": 0,
        "start": "2017-03-17 16:58:20.820315",
        "stderr": "",
        "stdout": "Foo bar",
        "stdout_lines": [
            "Foo bar"
        ],
        "warnings": []
    }
}

PLAY [vagrant.local] ***********************************************************

TASK [setup] *******************************************************************
ok: [vagrant.local]

TASK [debug] *******************************************************************
ok: [vagrant.local] => {
    "testvar": "VARIABLE IS NOT DEFINED!"
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0
vagrant.local              : ok=2    changed=0    unreachable=0    failed=0

Okazuje się jednak, że wystarczy drobna zmiana, żeby “dobrać się” do naszej zmiennej. Dla czytelności prezentuję tylko drugą część playbooka:

- hosts: vagrant.local
  become: no

  tasks:
  - debug: var=hostvars['localhost']['testvar']

Po wywołaniu zmodyfikowanego playbooka otrzymujemy w tym zadaniu wartość naszej zmiennej:

TASK [debug] *******************************************************************
ok: [vagrant.local] => {
    "hostvars['localhost']['testvar']": {
        "changed": true,
        "cmd": "echo \"Foo bar\"",
        "delta": "0:00:00.001697",
        "end": "2017-03-17 17:03:01.279967",
        "rc": 0,
        "start": "2017-03-17 17:03:01.278270",
        "stderr": "",
        "stdout": "Foo bar",
        "stdout_lines": [
            "Foo bar"
        ],
        "warnings": []
    }
}

Migracja z rvm do rbenv na mac OS

Na początek usuwamy wszystko co dotyczy RVM:

rvm implode

# ręcznie usuwamy (jeśli istnieje) plik:
rm ~/.rvmrc 

# oraz wpisy dotyczące RVM z:
.profile
.bash_profile
.bashrc
.zshrc

Następnie instalujemy rbenv przy pomocy brew:

brew install rbenv ruby-build

Lub ściągając z git hub’a

git clone https://github.com/rbenv/rbenv.git ~/.rbenv
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

Dodajemy rbenv do PATH:

# do .bash_profile lub .zshrc dodajemy:
export PATH="$HOME/.rbenv/bin:$PATH"

Oraz uruchamiamy:

rbenv init 

I uzupełniamy wskazany plik odpowiednim wpisem.

Aby zainstalować odpowiednią wersję ruby:

rbenv install 2.4.0

Możemy nadal używać plików .ruby-version wpisując w nie wersję ruby której chcemy używać w danym projekcie.

Synchroniczne uruchamianie workerów Sidekiq

Sidekiq pozwala na wykonywnie określonych zadań asynchronicznie, “w tle”. Najczęściej realizowane jest to za pomocą specjalnie stworzonych klas (workerów), które dzięki użyciu modułu Sidekiq::Worker zyskują metody z których możemy skorzystać aby zlecić wykonanie kodu w tle.

class FooWorker
  include Sidekiq::Worker

  def perform(foo_id)
    "Wartość foo_id wynosi: #{foo_id}"
  end
end

# wykonanie w tle
FooWorker.perform_async(1)
=> "d26cca4c2786f52e48da9520"

# wykonanie po wskazanym czasie
FooWorker.perform_in(10.seconds, 1)
=> "369aee857301ef89d7669821"

Czasem przydatne może być wykonanie kodu workera w ramach aktualnego wątku, bez planowania zadania w tle. Wbrew pozorom jest to bardzo łatwe - wystarczy pamiętać, że worker jest przecież regularną klasą Ruby, w związku z tym możemy po prostu powołać jego instancję i wykonać metodę perform:

FooWorker.new.perform(1)
=> "Wartość foo_id wynosi: 1"

Oczywiście, przy takim wywołaniu całkowicie pomijamy strukturę Sidekiq, tracąc tym samym kolejkowanie, ponawianie zadań itd. Może to być jednak bardzo przydatne w momencie, kiedy chcemy łatwo sprawdzić działanie kodu zamkniętego w workerze, np. w trakcie debugowania aplikacji.

Sortowanie NULL w PostgreSQL

W przypadku kiedy kolumna według której sortujemy dane pobierane z bazy PostgreSQL przybiera wartość NULL, kolejność wyników jest następująca:

  • dla sortowania w porządku rosnącym (ASC), wartości NULL zostaną umieszczone jako ostatnie,
  • dla sortowania w porządku malejącym (DESC), wartości NULL zostaną umieszczone jako pierwsze.

Nie zawsze jednak jest to preferowane zachowanie - łatwo wyobrazić sobie sytuację, kiedy puste dane chcemy zawsze prezentować jako ostatnie (lub jako pierwsze) - niezależnie od przyjętego porządku sortowania.

Można to łatwo wymusić jawnie wskazując w momencie sortowania w jakim porządku mają być zwracane wartości NULL. Aby to osiągnąć, należy do warunku sortowania - ORDER BY column_name ASC | DESC - dodać:

  • NULLS LAST - jeżeli wartość NULL ma być umieszczona na końcu wyników,
  • NULLS FIRST - jeżeli wartość NULL ma być umieszczona na początku wyników.

Przykładowo, dla danych:

-------------------
| id | name       |
-------------------
| 1  | Zofia      |
| 2  | NULL       |
| 3  | Alicja     |
-------------------

możemy sortować w następujący sposób:

# NULLe zawsze ostatnie
SELECT id, name FROM table_name ORDER BY name ASC NULLS LAST;
=> [3, Alicja], [1, Zofia], [2, NULL]

SELECT id, name FROM table_name ORDER BY name DESC NULLS LAST;
=> [1, Zofia], [3, Alicja], [2, NULL]

# NULLe zawsze pierwsze
SELECT id, name FROM table_name ORDER BY name ASC NULLS LAST;
=> [2, NULL], [3, Alicja], [1, Zofia]

SELECT id, name FROM table_name ORDER BY name DESC NULLS LAST;
=> [2, NULL], [1, Zofia], [3, Alicja]

Więcej informacji dostępne jest w dokumentacji PostgreSQL.

Docker - przydatne polecenia

Kilka użytecznych poleceń przy pracy z docker’em.

Lista kontenerów z informacją o zajmowanym miejscu na dysku:

  docker ps -s

Podgląd używanych zasobów przez poszczególne kontenery:

  docker stats

Usuwanie nieużywanych kontenerów:

  docker rmi -f $(docker images | grep "<none>" | awk "{print \$3}")

watch unicorn - sprawdzenie kiedy się unicorn przeładuje

Aby nie wpisywać co kilka sekund polecenia sprawdzającego czy np. workery unicorna się przeładowały, możemy użyć polecenia:

  watch 'ps aux | grep master | grep unicorn | grep -v grep'

Po słowie kluczowym watch podejemy polecenie jakie ma zostać wykonane. Polecenie będzie powtarzane co 2 sekundy, aby zmienić interwał używamy opcji -n lub --interva.