úterý 25. září 2007

Ruby a Rails konzole

Dnes pár triků pro práci s irb a Rails konzolí. Pozor: práce s Ruby konzolemi je návyková. Já používám konzole hlavně v následujících scénářích:
  • elaborace jazykových a datových konstrukcí (to je vhodné zájmena u modelů z RoR, např. pokud ladíte komplikovaný SQL dotaz)
  • zkoumání vlastností tříd a objektů:

    irb(main):008:0> [1].methods.select {|m| m =~ /^s/}

  • náhrada za Unix-like find, xargs a grep:

    find . -name \*rb

    irb(main):001:0> require 'find'
    => true
    irb(main):002:0> Find.find('.') {|f| puts f if f =~ /.*\.rb$/}

    find . -name \*rb | xargs grep 'neco'

    irb(main):003:0> Find.find('.') {|f| puts f if File.file?(f) and IO.read(f) =~ /neco/}

  • náhrada za awk + sed
  • kalkulačka :-)
To, co platí pro irb, platí i pro Rails konzoli, ne však naopak.

irb
  • Přístup na poslední návratovou hodnotu
Konzole poskytuje proměnou '_', která vrací návratovou hodnotu posledního úspěšně provedeného příkazu:


irb(main):001:0> 1 + 1
=> 2
irb(main):002:0> _
=> 2
  • Uchování historie příkazů mezi spuštěními konzole
Napsali jste komplikovaný finder na modelu RoR a zjistili, že musíte zrestartovat konzoli, aby se vám nahrály změny provedené v kódu (viz níže). Zde je řešení. Přidejte do ~/.irbrc následující:

require ‘irb/completion’
require ‘irb/ext/save-history’
ARGV.concat [ “–readline”, “–prompt-mode”, “simple” ]
IRB.conf[:SAVE_HISTORY] = 100
IRB.conf[:HISTORY_FILE] = “#{ENV[’HOME’]}/.irb-save-history”


Rails konzole

  • Reloading
Konzole načítá soubory zdrojových kódu vaší aplikace při jejím startu. Aby nebylo nutné restartovat konzoli po každé úpravě kódu, existuje příkaz reload!, který zdrojové kódy nahraje znovu. Bohužel, výše uvedené neplatí pro kódy z adresářů lib nebo vendor.
  • Polidštěná vizualizace objektů
RoR rozšiřují třídu Object o metodu to_yaml, která převadí instanci třídy do formátu YAML. Dokonce existuje funkce 'y', která na svém parametru metodu to_yaml vyvolá:

>> l = Login.find 1
=> #"2999-12-18 00:00:00", "nick"=>"max", "id"=>"1", "subject_id"=>"1", "password"=>"5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"}>
>> puts l.to_yaml
--- !ruby/object:Login
attributes:
expiration_date: 2999-12-18 00:00:00
nick: max
id: "1"
subject_id: "1"
password: 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
=> nil
>> y l
--- !ruby/object:Login
attributes:
expiration_date: 2999-12-18 00:00:00
nick: max
id: "1"
subject_id: "1"
password: 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
=> nil

úterý 11. září 2007

CZ podcast volume #15 a doplnění kritického pohledu

Tento příspěvek je doplněním CZ podcast volume #15 ve smyslu kritického pohledu na framework Ruby on Rails.

Sám jsem fanoušek RoR, ale dle mého názoru neuškodí trocha kritiky na framework, který má v podstatě jen kladné reference marketinkové povahy. Takže zde je několik postřehů z praxe...

Technologická oblast:
  1. Single threaded - RoR není thread safe, takže synchronizace je zajištěna synchronizovaným blokem v metodě Dispatcher.dispatch, která deleguje příchozí HTTP request na konkrétní kontroler. To je důvodem, proč se pro zajištění výkonostních požadavků typicky rozbíhá několik serverů Mongrel ve spojení s reverzním proxy serverem a load balancerem, např. Apache. Škálovatelnost v oblasti konkurenčních přístupů na systém se tak nezajišťuje na úrovni threadů, jako ve světě Javy, ale na úrovni procesů.
  2. Distribuované transakce - nejsou, tzn. žádná transakce pres dva databázové stroje, přes databázi a MOM (Message Oriented Middleware) nebo přes několik systémů s JCA adaptérem...
  3. SQL Prepared Statements - v současné době nelze (i když existuje plugin, který se snad stane součástí jádra RoR). To má dva neblahé důsledky. Za prvé to uzavírá cestu, která elegantně chrání systém před SQL injekcemi. A za druhé opět výkonost. Každý SQL výraz se musí na straně serveru opět parsovat.
  4. ActiveRecord a SQL neefektivita - ActiveRecord odstíní vývojáře od samotného SQL a tím vede vývojáře k produkci kódu, který je z pohledu SQL vysoce neefektivní. S tím lze bojovat, a RoR k tomu nabízí prostředky, ale pak už to není ta krásná a jednoduchá aplikace z prvních stránek knížek o RoR.
  5. Composite primary keys - není podporován. Osobně považuji surrogate key za dobrý postup, ale stěží aplikovatelný na již existující relační schéma, nad kterým se má postavit systém.
  6. MOM rozhraní - neexistuje žádné rozhraní na MOM jako JMS ve světě Javy. To je nedostatek pro tak důležitou integrační technologii, jakou jsou messaging systémy.
  7. Database Connection Pool - samozřejmě existuje :) ale nedosahuje takových konfiguračních kvalit jako existující CP ze světa Javy.
Politická oblast:
  1. Neexistuje žádný veliký hráč ve světě ICT, který by se k RoR hlásil. Tím pádem nemají RoR masivní podporu, kterou by nová enterprise tehnologie potřebovala.
  2. Nedostatečné prostředky pro integraci s existujícími složkami enterprice systémů, jako jsou messagingové systémy nebo doménové řadiče a LDAP.
  3. Další technologie ve světě enterprise vývojových platforem.
  4. Málo specialistů na postavení stabilního vývojového týmu.

sobota 1. září 2007

HenPlus == SQL shell

Máte rádi příkazovou řádku? Já ano. S prostředky na průchod historií příkazů a s automatickým doplňování výrazů je to mocná a efektivní zbraň. Z těchto důvodů docela rád používám SQL terminálové klienty, jako je SQL*Plus (Oracle) nebo psql (PostgreSQL).

Tolik teorie. Praxe bohužel naráží na moje limity ohledně schopnosti zapamatovat si a dlouhodobě udržet v paměti množtví proprietárních drobností, které z uvedených toolů dělají plnohodnotný pracovní nástroj. Teď mluvím o příkazech jako show tables nebo quit (sqlplus), resp. \dt nebo \q (psql).

Kudy na sjednocení? Díky přenositelnosti a JDBC rozhraní se celkem logicky nabízí Java. Dlouho jsem používal DbVisualizer, který však nemá výše uvedenou sílu terminálových klientů. A pak, blesk z čistého nebe: HenPlus.

Vypíchnu jen některé vlastnosti a zbytek nechám na laskavém čtenáři s odkazem na dokumentaci projektu:
  • bash like vlastnosti prostřednictvím knihovny readline
  • jednotné připojení ke všem typům databází pomocí příkazu connect jdbc:postgresql://localhost/foo
  • podpora více paralelních připojení a přepínání mezi nimi
  • auto kompletace na úrovni příkazů i databázových objektů
  • definice zástupců (alias): alias ls tables
  • definice vlastních proměných: set-var tabname footab; select count(*) from ${tabname};
  • dump tabulek nezávislý na databázi