wtorek, 14 stycznia 2020

Hook do automatycznego deploy'u po pushu do repozytorium zdalnego

Założenia:

  • masz lokalne repo z poprawnie skonfigurowanym remote origin (pisałem o tym m.in. w artykule o zainicjowaniu danymi zdalnego repo)
  • masz zdalny serwer na którym znajduje się origin (tzw. "bare" np. w katalogu /srv/git/my_app.git)
  • na tym samym hoście, na którym znajduje się "bare" repo, zdeployowana jest aplikacja, gdzie kod znajduje się w katalogu /var/www/my_app/code
  • chcesz aby po lokalnym git push origin master i zaktualizowaniu się repozytorium zdalnym, wysłane zmiany w kodzie zostały automatycznie zaciągnięte do aplikacji

Krok 1

W katalogu /srv/git/my_app.git/hooks tworzymy plik o nazwie post-receive

Krok 2

W utworzonym właśnie pliku post-receive umieszczamy taką zawartość:
#!/bin/sh

unset $(git rev-parse --local-env-vars)
cd /var/www/my_app/code
git pull
touch tmp/restart.txt

Krok 3

Plik post-receive czynimy wykonywalnym, np.tak:
chmod 755 post-receive

No i właściwie od tej chwili po twoim git push origin master możesz cieszyć się autodeployem. Całość pomysłu zaciągnąłem z https://stackoverflow.com/questions/5769568/how-to-set-up-a-git-hook-so-that-after-pushing-to-ssh-peterfoo-com-bar-com

poniedziałek, 13 stycznia 2020

Jak pokazać wielkość katalogu w systemie Linux

Wyświetlając katalogi tylko z zagłębienia pierwszego poziomu. Zlicza wszystkie poziomy! Właśnie tak:

du -h --max-depth=1

Można też to posortować:

du -h --max-depth=1 | sort -h
Opcja -h pokazuje z liczbami dogodnymi do czytania dla człowieka.

Znajdowanie pliku w systemie Linux przy pomocy komendy find

Zawsze oczywiście zapominam składnię, wiec właśnie zapisuję.

wyszukaj w katalogu, w którym się aktualnie znajduję, w nazwie pliku, bądź katalogu słówko "jmeter":

find . -name '*jmeter*'

To samo tylko dla plików:

find . -name '*jmeter*' -type f

To samo tylko dla plików nie kończących się na "png":

find . -name '*jmeter*' -type f -not -name '*png'

To samo tylko dla maksymalnego zagłębienia się w katalog drugiego poziomu:":

find . -name '*jmeter*' -type f -not -name '*png' -maxdepth 2

Pokaż wszystkie katalogi wewnątrz folderu bierzącego

find . -type d

Znajdź pliki, które były edytowane mniej niż 10 minut temu

find . -type f -mmin -10

Znajdź pliki, które były edytowane więcej niż 10 minut temu

find . -type f -mmin +10

Znajdź pliki, które były edytowane więcej niż minutę temu, ale mniej niż 10 minut temu

find . -type f -mmin +1 -mmin -10

Znajdź pliki, które były edytowane mniej niż 20 dni temu

find . -type f -mtime -20

Znadź pliki, które są większe niż 5 MB

find . -size 5M

Znajdź puste pliki

find . -empty

Znajdź pliki, które mają uprawnienia 775

find . -perm 775

Znajdź wszystkie obrazki .png w bieżacym katalogu i przypomocy komendy chown zmień właściciela na test_user i grupę na test_group
Nawiasy klamrowe {} są placeholderem imitującym plik, a znak plus na końcu + mowi, że to koniec komend.

find . -type f -name "*.png" -exec chown test_user:test_group {} +

Znajdź wszystkie obrazki jpg tylko w bieżącym katalogu (nie w podkatalogach czyli użyjemy -maxdepth 1 gdzie jedynka to ilość w głąb katalogów) i usuń je. To zagłebienie w katalogi jest ważne, gdyż domyślnie komenda find idzie do ostatniego katalogu wgłąb.

find . -type f -name "*.jpg" -maxdepth 1 -exec rm {} +

Uwaga! Wszędzie ciapki są ważne. Ciapki można zastapic cudzysłowami i vice versa. Ważne tylko, aby stosować je konsekwentnie.

wtorek, 7 stycznia 2020

* - (gwiazdka, asterix) czyli operator splat w Ruby

Zasadniczo służy do przyjęcia wielu argumentów do metody. Na przykład tak:
def my_method(*args)
  args.each {|arg| puts arg}
end

a wywołanie:
my_method(:a, "ala ma kota", 1, 2, 3.14)

A tak przy okazji... splat ma sporo więcej możliwości.

Opisane fajnie tutaj: https://www.honeybadger.io/blog/ruby-splat-array-manipulation-destructuring/

środa, 1 lipca 2015

OR zamiast AND w zapytaniach Rails

Przy zapytaniu where - wynikowy SQL jest generowany zazwyczaj z AND. Na przykład w tym zapytaniu wszędzie w SQL'u jest AND:
VariantDetail.joins(product_detail: {product: [:channel, :type]},
                    variant: {starpacks: :version})
             .all_active
             .where(code: cover[:id], value: value,
                    pkb_cats_discr: {percent: percent.to_i},
                    pkb: {channel_id: channel.id, type_id: @type.id},
                    version: {code: ver.code})

Mi zaś, chodziło o to, aby kolumna percent była rozważana dla dwóch wartości: jako 0 (zero) albo NULL.
Okazało się, że można to zrobić w dość prosty sposób. Wystarczy użyć w klauzuli where, tablicy.
Na przykład tak:
{percent: [0, nil]}
co skutkuje takim kompletnym zapisem:
VariantDetail.joins(product_detail: {product: [:channel, :type]},
                    variant: {starpacks: :version})
             .all_active
             .where(code: cover[:id], value: value,
                    pkb_cats_discr: {percent: [0, nil]},
                    pkb: {channel_id: channel.id, type_id: @type.id},
                    version: {code: ver.code})

czwartek, 25 września 2014

Sumowanie wartości w rekordach wybranego już zestawu z bazy danych

Rozważmy taki scenariusz: wybraliśmy wszystkich klientów, którzy w zadanym okresie kupili więcej niż jeden towar z naszego sklepu internetowego. Otrzymaliśmy zestaw klientów wraz z ilością zakupionych towarów i sumą cen tych towarów per klient.
A co jeśli chcemy zsumować ilość wszystkich towarów zakupionych przez klientów w tym zestawie?
Zawsze robiłem to tak:
  @customers.sum(&:amount)
No i fajnie. Działało. Działało do momentu, dopóki nie sumowałem ilości przepracowanych godzin, które to godziny było obliczane z dat. Z niewiadomych przyczyn generowana kolumna była w formacie string i sumowanie tworzyło wielki string.

Można to zrobić tak:
  @customers.sum{|customer| customer.amount.to_i}
Problem znika.

piątek, 19 września 2014

Wstawienie własnego parametru do ścieżki Paperclip'a

W którymś ze swoich projektów potrzebowałem aby obrazki gromadzone przez użytkowników aplikacji gromadzone były w katalogach firm, do których należą owi użytkownicy. Oczywiście w parametrze "path" Paperclip'a nie występuje nic podobnego do "firm_id".

Innymi słowy chciałem zapisać coś takiego:
has_attached_file :scan_picture, :styles => {:thumb => '50x50>'},
                  :default_url => '/images/:style/missing.png',
                  :url => "/system/scan_pictures/:firm_id/:id/:style/:basename.:extension",
                  :path => ":rails_root/public/system/scan_pictures/:firm_id/:id/:style/:basename.:extension"


Jest to jednak możliwe :-)
Zrobiłem tak:
w katalogu /config/initializers stworzyłem plik paperclip_interpolations.rb
w tym pliku umieściłem zapis:
Paperclip.interpolates('firm_id') do |attachment, style|
  attachment.instance.move_out.customer.firm_id.to_s.parameterize
end
Tłumaczyć to można tak:
Weź egzemplarz klasy, która wywołuje dołączanie pliku (attachment.instance), pobierz z niego obiekt wyjazd (move_out), a z niego klienta i firmę, do której klient należy. Przekształć firm_id na string i użyj metody prametrize.
No i aby powyższe lepiej zrozumieć można przytoczyć jeszcze specyfikację MoveOut (wyjazd):
class MoveOut < ActiveRecord::Base
  belongs_to :customer
end