Dekorator w Ruby

Dekorator przyjmuje w konstruktorze obiekt i dodaje do niego nowe zachowania. Przykładem dekoratora jest Presenter – klasa dodająca do obiektu możliwość zaprezentowania się, np. w postaci sformatowanego Stringa, XML-a czy JSON-a. Na wroc_lover.rb Piotr Szotkowski pokazał bardzo fajny sposób tworzenia dekoratorów z użyciem SimpleDelegator. Zysk polega na uniknięciu boilerplate kodu – wszystkie metody dostępne na wejściowym obiekcie stają się dostępne bezpośrednio w dekoratorze.

require 'delegate'

class Address
  # extend with your favourite persistence solution or:
  attr_accessor :street, :postcode, :city, :country

  def initialize args = {}
    args.each { |key, value| send "#{key}=", value }
  end
end

class PolishAddress < SimpleDelegator
  def initialize address
    super address
  end

  def formatted
    [street, "#{postcode} #{city}", country].join "\n"
  end
end

Czyli mamy i ładnie (SRP), i zwięźle (no boilerplate code). Jeśli natomiast potrzebujemy Presentera bazującego na więcej niż jednym obiekcie, z pomocą przyjdzie mixin Forwardable, również z stdlib:

require 'forwardable'

class PolishEnvelopeAddress
  extend Forwardable

  def initialize args
    @person  = args.fetch :person,  Person.new
    @address = args.fetch :address, Address.new
  end

  def_delegators :@person,  :given_names, :surname
  def_delegators :@address, :street, :postcode, :city, :country

  def formatted
    ["Sz.P. #{given_names} #{surname}",
      street, "#{postcode} #{city}", country].join "\n"
  end
end
Posted in polskie, programowanie, rails, ruby, technologia | 8 Comments

Do zobaczenia na wroc_love.rb!

Moi wierni czytelnicy (łudzę się, że są tacy ;)) – do zobaczenia na wroc_love.rb!

Patrząc po prezentacjach, konferencja zapowiada się na taki Ruby OO summit i świetnie wpisuje się w ostatnie trendy w railsowym świecie. Żyliśmy The Rails Way przez wiele lat i dojrzeliśmy do następnego etapu ewolucji – The Right Way.

Cóż to jest The Right Way? To stosowanie najlepszych praktyk, nawet wtedy gdy  kłóci się to z The Rails Way / The Golden Path ;-). Jakież to praktyki? Ano na przykład:

  • Single-Responsibility-Principle na czele z oddzieleniem logiki biznesowej od persystencji (asta la vista fat models)
  • Izolacja od frameworków (Railsy nie są Twoją aplikacją)
  • Architektura sterowana przypadkami użycia (przykład)
  • Security-by-default
  • …itd

See U!

Posted in lifestyle, polskie, programowanie, rails, ruby, technologia | 2 Comments

Uncle Bob: decouple your app from Rails

Robert C. Martin in his famous keynote “Architecture: The Lost Years” says we, the proud Rails programmers, are doing it wrong. Uncle Bobs urges us to decouple our applications from frameworks. And Rails is no exception. According to Uncle Bob, we should build upon frameworks, but isolate from them.

I mean, really? Why should I? Is it even possible?

The expected benefits are profound.

But at what cost? How much overhead and boilerplate code do we need to achieve that? How can I decouple from ActiveRecord? I love the convenience and white magic ActiveRecord and Rails stack is giving to me!

I’m in the process of developing an experimental application which tries to answer those questions. The initial findings are very encouraging!

Posted in english, programowanie, rails, ruby, science, technologia | 1 Comment

Default transaction isolation level comparison in MySQL, PostgreSQL, Oracle and MS SQL Server

When building software you should understand what level of transaction isolation your RDBMS guarantees. Do you? I meen, how much of the “I” in the ACID we have? Here are the default transaction isolation levels in a popular relational database management systems:

RDBMS Default transaction isolation level
ANSI SQL Standard Serializable
SQLite Serializable
MySQL Repeatable Read
PostgreSQL Read Committed
Oracle Read Committed
MS SQL Server Read Committed

If you are unsure what that means, Wikipedia has a nice explaination.

Posted in english, programowanie, rails, ruby, science, technologia | 5 Comments

Opis stosu Racka w Rails 3.2

Właśnie wyszły stabilne Railsy 3.2. Przy tej okazji przyjrzałem się stosowi Racka.

Za co odpowiedzialne są poszczególne middleware’y?

Stos Rails 3.2 wygląda następująco (kolejność od najwcześniej do najpóźniej uruchamianych middleware’ów, jak przy rake middleware):


# Serwuje statyczne pliki
use ActionDispatch::Static

# Synchronizuje obsługę żądania na muteksie
use Rack::Lock

# Instancjuje backend cache'a (LocalStore.new)
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000002964ba8>

# Mierzy czas żądania i dokleja nagłówek X-Runtime
use Rack::Runtime

# Nadpisuje prawdziwą methodę HTTP parametrem _method 
# lub nagłówkiem HTTP X_HTTP_METHOD_OVERRIDE
use Rack::MethodOverride

# Loguje pierwszą wzmiankę o żądaniu, np.: 
# Started GET "/dupa" for 127.0.0.1 at 2012-01-21 12:18:28 +0100
use Rails::Rack::Logger

# Przekazuje nagłówek X-Request-Id z żądania do odpowiedzi aby umożliwić 
# śledzenie żądania przez stos firewalli, load balancerów, serwerów itp.
use ActionDispatch::RequestId

# Łapie wszelkie wyjątki aplikacji.
# Robi rescue Exception, a więc także SyntaxError, NoMemoryError itd.
# Dla żądań zdalnych renderuje statyczne strony błędów (np. public/500.html).
use ActionDispatch::ShowExceptions

# Łapie wszelkie wyjątki aplikacji.
# Robi rescue Exception, a więc także SyntaxError, NoMemoryError itd.
# Dla żądań lokalnych renderuje deweloperski stack trace.
# Dla żądań zdalnych propaguje wyjątek w górę stosu czyli w praktyce do
# ActionDispatch::ShowExceptions.
use ActionDispatch::DebugExceptions

# Usiłuje ustalić oryginalne IP klienta odsiewając lokalne i zdalne proxy
use ActionDispatch::RemoteIp

# Ustawia nagłówek odpowiedzi X-Sendfile w przypadku serwowania
# statycznego pliku aby przerzucić pracę na serwer, który zrobi
# to wydajniej niż Ruby (o ile jest do tego skonfigurowany).
use Rack::Sendfile

# Odpowiada za reloading kodu w trybie deweloperskim.
use ActionDispatch::Reloader

# Woła callbacki before, after i around akcji kontrolera
use ActionDispatch::Callbacks

# Zwraca połączenie do puli jeśli pojawi się wyjątek 
# (o ile request nie pochodzi z testów integracyjnych)
use ActiveRecord::ConnectionAdapters::ConnectionManagement

# Klasyczny cache zapytaniowy. Kluczem są Stringi z ostatecznymi 
# zapytaniami SQL.
use ActiveRecord::QueryCache

# Renderuje ciastka ustawione w kontrolerze do nagłówków HTTP 
# Robi to z pomocą Rack::Utils
use ActionDispatch::Cookies

# Zapisuje dane sesji do skonfigurowanego backendu, np. do ciastka
use ActionDispatch::Session::CookieStore

# Usuwa wiadomość flash po użyciu
use ActionDispatch::Flash

# Buduje Hasha params zgodnie z railsowymi konwencjami 
# przekazywania parametrów
use ActionDispatch::ParamsParser

# Usuwa body dla żądań metodą HEAD
use ActionDispatch::Head

# Porównuje nagłówki ETag (żądania z odpowiedzią) oraz Last-Modified
# dążąc do zwrócenia 304 Not Modified i wyzerowania body
use Rack::ConditionalGet

# Oblicza i dokleja nagłówek ETag odpowiedzi
use Rack::ETag

# Dodaje nagłówek X-UA-Compatible do odpowiedzi w zależności od opcji
# config.action_dispatch.best_standards_support za pomocą której
# można wymusić tryb quirks lub strict dla IE.
use ActionDispatch::BestStandardsSupport
Posted in polskie, programowanie, rails, ruby, technologia | 7 Comments

Software Craftsmanship

Załączam prezentację “Software Craftsmanship – od studenta do profesjonalisty”, którą wygłosiłem na Wydziale Elektroniki i Technik Informacyjnych Politechniki Warszawskiej 19 stycznia 2012:

Prezentacja: https://github.com/downloads/qertoip/Prezentacja-Software-Craftsmanship/software_craftsmanship.html

Źródła: https://github.com/qertoip/Prezentacja-Software-Craftsmanship

 

Posted in clojure, git, javascript, lifestyle, polskie, programowanie, rails, ruby, technologia | Leave a comment

[Solved] Nano copy paste

Nano is the closest-to-being-sane, widely available text editor for Linux. While still fucked up, you can get used to it in several hours. One of the biggest headaches seems to be selecting, copying and pasting. Nano help isn’t really helpful here, so let’s make it clear. Continue reading

Posted in english, linux, programowanie, rant, technologia | Leave a comment

[Solved] How to run each MiniTest::Spec in a transaction?

How to run each MiniTest::Spec in a transaction rolled-back upon finish? Simply add this to your test_helper.rb after requiring minitest/autorun:


# Monkey patch to ensure each test is run in a rolled back transaction
class MiniTest::Spec

  def run( *args, &block )
    value = nil

    begin
      ActiveRecord::Base.connection.transaction do
        value = super
        raise ActiveRecord::Rollback
      end
    rescue ActiveRecord::Rollback
    end

    return value  # The result of run must be always returned for the pretty dots to show up
  end

end

Posted in english, programowanie, rails, ruby, technologia | Leave a comment

[Solved] How to auto connect to a VPN on startup in Ubuntu 11.10?

How to automatically connect to a VPN on startup (login) in Ubuntu 11.10 (oneiric ocelot)?

What did NOT work

  • Option “connect automatically” in the Network Manager VPN configuration. This option has never worked, the bug is open for over 3 years and there seem to be no hope for the official fix.
  • The vpnautoconnect daemon does not work in my particular case. As of time of writing there is no deb package for Ubuntu 11.10 amd64. Source code version seems to have messy / inconvenient dependencies I was not eager to fulfill.

What DID work

I solved the problem using /etc/network/if-up.d/ hooks. Scripts in this dir are executed whenever any network interface is up, so it is (probably) the right place to (try to) start a VPN connection.

Here is the script to put in the aforementioned directory. Script name doesn’t matter:

#! /bin/bash

REQUIRED_CONNECTION_NAME="singularity"      # change singularity to your network connection name
VPN_CONNECTION_NAME="airvpn"                # change airvpn to your VPN connection name

activ_con=$(nmcli con status | grep "${REQUIRED_CONNECTION_NAME}")
activ_vpn=$(nmcli con status | grep "${VPN_CONNECTION_NAME}")
if [ "${activ_con}" -a ! "${activ_vpn}" ];
then
    nmcli con up id "${VPN_CONNECTION_NAME}"
fi

The “singularity” is a name of my wifi connection and “airvpn” is a name of the VPN connection. Replace them with yours (visible in the Network Manager widget).

Add execution permission (i.e. chmod +x /etc/network/if-up.d/connect-to-vpn where connect-to-vpn is the name of the script).

That’s all. Test it by turning off and on your network connection. VPN should now connect automatically.

Posted in english, programowanie, technologia | 20 Comments

Rails partials: nigdy nie wołaj render() w pętli

Wołanie <%= render(…) %> w pętli jest straszliwie niewydajne bo railsy owijają każde wywołanie rendera w benchmark(). ZTCW nie da się tego wyłączyć. Problem jest zauważalny już przy 10-20 powtórzeniach. Przy długich listach itemów, liczących np. 100 pozycji, jest to już prawdziwy horror – renderowanie ponad 1s.

Wydajna alternatywa:

<%= render @collection %>

np.

<%= render @users %>

W powyższym railsy dla każdego obiektu z listy @users sprawdzą nazwę modelu (User) i wyrenderują partial _user.html.* (konwencja). Benchmark zostanie wywołany tylko raz, stąd radykalna poprawa wydajności.

Posted in polskie, programowanie, rails, ruby, technologia | 6 Comments