Čtete statickou verzi tohoto blogu. Nové články autora nalezenete v angličtině na blogu Restafari.

Ruby on Rails a revoluce ve vývoji pro web. Část druhá: Active Record

Kategorie: Rails

Publikováno 17. 06. 2007 v 01:00

19 komentářů (poslední napsal/a karmi)


V prvním článku o Ruby on Rails jsme se zabývali základními filosofickými principy, na nichž je založen jazyk Ruby — jazyk, v němž jsou Rails napsány a v němž jsou psány Rails aplikace. Viděli jsme, že jeho úsporná syntaxe je navržena tak, aby se programátorovi nepletla do cesty, a umožnila mu co nejsnazší a nejelegantnější vyjádření „myšlenky“:

5.times { print "Hurá! " }
=> ‚Hurá! Hurá! Hurá! Hurá! Hurá!‘

V tomto článku bych se chtěl věnovat tomu, co dělá Rails tím, čím jsou. Jestliže nevíte o Rails nic nebo téměř nic, než budete číst dál, podívejte se na patnáctiminutové video v angličtině, kde autor naprogramuje kompletní blog: Creating a weblog in 15 minutes.

… hotovo? Tak můžeme jít dál. Video je samozřejmě působivé a jsou v něm jasně vidět inspirační zdroje v Ruby. Asi je vám jasnější, proč Computerworld zařadil Rails mezi pět nejvýznamnějších technologií pro rok 2007. Napsat funkční aplikaci v čistém kódu a s použitím transparentních abstraktních vrstev za čtvrt hodiny je slušný výkon.

Video také naznačuje odpověď na otázku, proč David Heinemeier Hansson (dále jen DHH) Ruby on Rails vytvořil: protože ho bavilo vidět výsledky své práce, ale nebavila ho práce samotná („Happy Programming with Ruby On Rails“). Takže po pěti letech vývoje různých aplikací v PHP vytvořil — víceméně jako „vedlejší produkt“ při práci na projektu Basecamp — framework Rails. (Pro nabízející se srovnání Ruby s PHP a celou diskusi „nechápu, proč jsi Basecamp neudělal v PHP“ čtěte archivní diskusi na toto téma.) Oproti „běžné práci“ webového vývojáře vzniká výsledek v uvedeném videu snad jakoby sám od sebe, aplikace roste jako živý organismus.

Proč je tomu tak? Protože autor nedělá a především nevymýšlí žádné „nutné a nudné“ postupy: konfigurace, mapování URL, nepíše ani SQL dotazy. Všechny tyto základní věci se dějí jakoby „samy od sebe“. Autor se zabývá jen logikou aplikace samotné. Proč je tomu tak? Protože:

„Toto je sněhová vločka. Vaše aplikace není jedna z nich. Většina věcí, které většina lidí dělá, není nijak unikátní. Vaše potřeby nejsou nijak ‚zvláštní‘.“

~ David Heinemeier Hansson, přednáška na konferenci Future Of Web Applications, únor 2006

Konvence má přednost před konfigurací

Nejste unikátní – to je naprosto klíčový princip designu Rails: webové aplikace jsou si v podstatě podobné jako vejce vejci. Načítají data z databáze, transformují je do datových struktur programovacího jazyka (pole, hashe, objekty), provádějí s nimi manipulace (řazení, filtrování, transformace textů), vypisují je do HTML, a prostřednictvím formulářů je zase sbírají, provádějí s nimi manipulace a ukládájí je do relačních databází. Interaktivita aplikace je tvořena odkazy a formulářovými prvky, které načítají různá URL.

Problém je v tom, že začínat psát běžnou webovou aplikaci v PHP od příkazu mysql_connect a zabývat se dotazy do databáze typu SELECT * FROM articles ORDER BY published_at je absurdně vyčerpávající a nevýhodné. Proto vstupuje na scénu záležitost zvaná framework, byť by to byly jen dvě třídy na abstrakci připojení k databázi a na generování formulářů. Enterprise řešení s sebou zase většinou přinášejí takovou zátěž konfigurace, nastavování, provázání technologií nebo závislosti na platformě, že je v běžném provozu používají jen specifické projekty.

Proto se DHH rozhodnul ctít hlavní pravidlo: konvence má přednost před konfigurací. V určité analogii s Paretovým principem tvrdí, že většina frameworků selhává proto, že se snaží řešit všechno, všechny možné případy, abstrahovat až na úplně nejvyšší úroveň, a fetišizuje „teoreticky čistá řešení“. Hlavní pravidlo designu Rails pak konkrétně znamená např. to, že autor konfiguruje v aplikaci pouze to, co se liší od běžného nastavení — vytvoří-li tedy např. model Person, aplikace bude data automaticky hledat v databázové tabulce people (tedy v tabulce, která se jmenuje stejně jako model, avšak v množném čísle). Chce-li, aby aplikace načítala data z tabulky staff, musí tak učinit výslovně.

Ještě uvidíme konkrétně, jak Rails filosofii „nejjednodušší řešení je zpravidla nejsprávnější“ (viz Occamova břitva) uplatňuje prakticky ve všech svých hlavních rysech. Ale už jen díky tomuto svému přístupu: „Flexibilita je přeceňována. Omezení jsou osvobozující“ Rails vnesly do nekonečných technických debat o rychlosti interpreterů, o tom, jestli je XML lék na všechno, správném pojetí objektově orientovaného programování, a podobně, nikoliv pravdu, ale čerstvý vítr. Pojďme se tedy podívat na principy, na nichž jsou Rails postaveny.

Model-View-Controller

Vyjdeme-li z definice v prvním článku o Ruby on Rails, Rails jsou Model-View-Controller framework. Co to přesně znamená?

Model-View-Controller (dále MVC) je ustálený návrhový vzor v softwarovém vývoji, způsob, jak transparentně oddělit různé části aplikace (lhostejno či webové nebo desktopové) podle toho, jakou úlohu v ní hrají. Model se stará o čtení a zapisování dat a o manipulaci s nimi („Vrať mi seznam osob, kde název zaměstnavatele je ‚Škoda Auto‘, seřazený vzestupně podle příjmení“); data předává controlleru. Controller (česky někdy zvaný řadič) se stará o příjem vstupů ze strany uživatele aplikace („Proveď akci definovanou pro kliknutí na odkaz ‚Telefonní seznam‘“) a distribuci výstupů („Načti stránku s identifikátorem ‚telefonni-seznam‘“). View (česky zvaný též pohled, v kontextu webu též šablona) obsahuje grafické rozhraní aplikace samotné, s definovanými ovládacími prvky (tlačítka, roletky, odkazy, …) a „dírami“, do nichž se leje obsah, který do view předává controller.

Schéma Model-View-Controller architektury

Jestliže se podíváme na strukturu Rails aplikace, mělo by nám tedy být již pár věcí docela jasných:

  • app
    • controllers
    • helpers
    • models
    • views

Ve složce app se nacházejí složky pro controllery, modely, i view. Tyto tři složky jsou srdcem Rails aplikace. Jaké jsou tedy konkrétní součásti Rails z pohledu MVC?

  1. Převedení dat z relační databáze na objekty Ruby (object-relational mapping), které zajišťuje Active Record (M)
  2. Směrování (routing) — mapování URL na vnitřní řídící prvky: controllery a jejich metody (funkce) a předávání dat mezi controllery a views (HTML šablonami) (C a V)
  3. Pomocné metody pro práci s HTML formuláři, Ajaxem, formátování řetězců, data a času a rozšíření Ruby tříd (M a V)

Další klíčové součásti Rails jsou:

  1. Skripty pro generování kódu, tedy např. šablon pro modely nebo controllery, tzv. lešení (scaffolding) aplikace, a dalších (script/generate)
  2. Konzole pro přímou interakci s modely běžící aplikace na příkazové řádce (script/console)
  3. Komunita a sdílení kódu — nejlepší kód je ten, který nemusíte psát. Tedy pokud nejste sněhová vločka. :)

Těchto šest oblastí nám dává dobrou představu o tom, jak jsou Rails uspořádány, a zároveň na nich lze dobře demonstrovat, v čem spočívá jedinečnost a elegance Rails. V tomto článku si projdeme pouze bod první, tedy Active Record — ostatním bodům se bude věnovat článek následující.

Active Record

Active Record je srdcem každé Rails aplikace. Tvoří jádro frameworku, a dokonale demonstruje intelektuální principy, na nichž jsou Rails založené, proto se u něj zdržíme nejprve a nejdéle.

Jak již bylo řečeno, Active Record je návrhový vzor, který mapuje databázové tabulky na třídy a převádí řádky na objekty (tedy instance tříd) a sloupce na jejich atributy: z názvu třídy (Article) odhadne název tabulky (articles). (Pro tento odhad obsahuje jednoduchou implementaci anglického slovníku, která je snadno rozšiřitelná.) Zároveň v implementaci Rails obsahuje výkonné nástroje na práci s daty (čtení, zápis, validace) a pro vztahy mezi tabulkami–objekty (ono Post has_many :comments, známé z podcastu).

To znamená, že odstiňuje vývojáře od „surového SQL“ (SELECT * FROM articles WHERE id = 1), od „vlastnoručního“ převádění výsledků dotazu na nativní datové entity a umožňuje efektivní práci na daleko vyšší úrovni. Zde je velmi dobře zřetelný intelektuální přínos Rails: 90% práce práce webového vývojáře spočívá právě v nekonečném psaní databázových dotazů SELECT ..., SELECT ... LEFT JOIN ..., UPDATE ... WHERE ..., případně v jejich konfiguraci pro nějaké obalující třídy či metody. To je samozřejmě z hlediska efektivity absurdní: pamatujeme si Matzovo diktum „čím více kódu, tím více chyb“. Jestliže se v 80% procentech případů nazývá tabulka v databázi stejně jako model, pouze v množném čísle (což dává logiku, obsahuje totiž více objektů, zatímco model reprezentuje povětšinou jeden objekt), nemá smysl tento fakt dokola a dokola potvrzovat v konfiguraci.

Proto místo dotazu SELECT * FROM articles WHERE id = 1, který nám k vrátí data:

+----+-------------+--------------------+--------+---------------------+
| id | title       | body               | author | created_at          |
+----+-------------+--------------------+--------+---------------------+
|  1 | Lorem Ipsum | Dolor sit amet ... | Cicero | 0000-00-00 00:00:00 | 
+----+-------------+--------------------+--------+---------------------+

v Rails vytvoříme třídu Article (ano, následující kód je úplný, nejsou potřeba inicializační ani žádné jiné metody):

class Article < ActiveRecord::Base
end

a napíšeme Article.find(1). Dostaneme objekt s příslušnými atributy:

--- !ruby/object:Article 
attributes: 
 id: "1"
 title: Lorem Ipsum
 body: Dolor sit amet ...
 author: Cicero
 created_at: 0000-00-00 00:00:00

Pokud bychom mermomocí chtěli, aby model používal tabulku clanky, myimportantprefix_articles, nebo jinou, není nic snazšího:

class Article < ActiveRecord::Base
  set_table_name "clanky"
end

Tím však možnosti, které nám Active Record pro efektivní práci při získávání dat dává, nekončí. Kromě prostého find, které hledá záznam dle sloupce id, můžeme využít jeho varianty:

  • Article.find(:all, :order => 'created_at DESC') nám vrátí všechny záznamy v tabulce articles seřazené sestupně dle data
  • Article.find_all_by_author('Cicero', :order => 'title') nám vrátí všechny záznamy konkrétního autora seřazené vzestupně podle názvu (tyto metody se v Rails nazývají dynamické dotazy, dynamic finders)
  • Article.find_all_by_author_and_title('Cicero', 'Lorem Ipsum') ukazuje, jak můžeme dynamické dotazy kombinovat

Bylo by asi ztrátou času vypisovat zde příslušné SQL dotazy, abychom si ukázali, kolik znaků (a tím i příležitostí k chybám) a energie jsme si ušetřili. Dynamické dotazy navíc krásně ukazují sílu objektově-relačního mapování.

Řekli jsme ale, že Active Record nám dává nástroje nejenom pro získávání dat, ale i pro manipulaci s nimi. Co když tedy chceme změnit některý atribut daného záznamu/objektu?

article = Article.find(1)
article.author = 'Seneca'
article.save

Jednodušší to být nemůže. Změním atribut objektu a ten uložím. Vypisovat zde ukázkové dotazy 'SELECT FROM ... UPDATE ... SET author='.$author.' WHERE id='.$id.', důvěrně známé všem webovým vývojářům, je pravděpodobně opět zbytečné: absolutní rozdíl v úrovni přístupu je zřejmý sám od sebe. Třídy odvozené od Active Record obsahují pochopitelně i metody create a destroy pro vytváření a mazání záznamů. (Active Record v Rails obsahuje také metodu find_by_sql pro specifické případy složitých dotazů, nebo například dotazů, které je třeba silně optimalizovat. Princip „konvence má přednost před konfigurací“ neznamená, že „konfigurace“, tedy odchylka od obvyklého, není možná.)

To ale stále není všechno, co nám Active Record poskytuje. Mapovat data z tabulek na „pole“ koneckonců umí kdekterá vlastnoručně stvořená knihovna pro PHP obalující připojení k databázi. Detailní popis Active Recordu přesahuje tento článek, ale pro naše ilustrační potřeby zmíníme dvě vlastnosti: validaci vstupních dat a vztahy mezi objekty.

Validace vstupních dat je jednou ze základních podmínek bezpečnosti a správné funkce webových aplikací. Přesto je přístup mnoha programátorů k ní více než laxní. Implementace Active Record v Ruby on Rails má funkce pro validaci zabudované. Vezměme si tedy definici třídy Article:

class Article < ActiveRecord::Base
  validates_presence_of :author
end

V prostém jazyce říká, že atribut author nesmí být prázdný (article validates presence of author), tedy jinými slovy: článek musí mít autora — což je logické. Co se tedy stane, když se pokusíme uložit článek, který nemá autora, tedy: jehož atribut author je prázdný řetězec?

article = Article.find(1)
article.author = ''
article.save!
=> ActiveRecord::RecordInvalid: Validation failed: Author can't be blank

Boom! Autor nesmí být prázdný. (Vysvětlení pro nadprůměrně všímavé: zatímco metoda save z prvního příkladu vrací hodnoty true nebo false podle toho, zda se povedlo záznam uložit, bang-metoda save! z druhého příkladu při neúspěchu operace vyvolá definovanou výjimku. K bang-metodám se ještě v rámci výkladu o Ruby vrátíme v některém z příštích článků.) Platí totéž, co pro ukládání záznamu výše: jednodušší to být nemůže. Připočteme-li k tomu to, že Active Record je v Rails implementovaný tak, že formuláře jsou předvyplněny hodnotami objektu, že při neúspěšném uložení Active Record vrací chybu pro každý atribut (a můžeme ji tedy snadno vypsat k příslušnému poli) a že mezi další validační funkce patří např. validates_length_of, validates_uniqueness_of, validates_format_of (využívající regulární výrazy), je opět zjevné, kolik kódu nám Rails šetří, kolik kódu vůbec nemusíme psát.

Poslední vlastností Active Record, kterou se v našem úvodu budeme zabývat, je podpora pro vztahy mezi objekty. Náš příklad s třídou Article totiž neodpovídá vývoji ve skutečném světě. Těžko bychom ve skutečné aplikaci měli autory článků uložené ve sloupečku tabulky articles. Ne, vyčlenili bychom pro ně zvláštní tabulku, pravděpodobně tabulku s názvem authors. Článek může mít více autorů, autor může napsat více článků, jde tedy o vztah n ku m. Rails je, jak dobře víme, framework pro skutečný svět, ne pro zjednodušené tutoriály, a proto nám poskytuje nástroje i pro relativně složité vztahy mezi entitami podobného typu. Stačí nám jen dobře definovat vztahy v deklaraci tříd (tento kód je opět úplný, pro pouhé vzájemné propojení tabulek-objektů více nepotřebujeme):

class Article < ActiveRecord::Base
  has_and_belongs_to_many :authors
end

class Author < ActiveRecord::Base
  has_and_belongs_to_many :articles
end

Nyní tedy vytvoříme nový článek, nového autora, a autora k článku přiřadíme:

article = Article.new
article.title = "Lorem Ipsum"

cicero = Author.new
cicero.name = "Cicero"
cicero.email = "cicero@senatus.gov"
cicero.save!

article.authors << cicero
article.save!

To nebylo těžké. Když se nyní podíváme na objekt article, vidíme, že obsahuje pole s autory:

>> print article.to_yaml
--- &id002 !ruby/object:Article 
attributes: 
  body: 
  title: Lorem Ipsum
  id: 2
  created_at: 2007-06-16 02:23:40.124124 +02:00
authors: 
- &id001 !ruby/object:Author 
  attributes: 
    name: Cicero
    id: 3
    email: cicero@senatus.gov

Zrovna tak z druhé strany, pokud bychom chtěli dostat seznam Ciceronových článků:

>> print cicero.articles.to_yaml
--- 
- !ruby/object:Article 
  attributes: 
    body: 
    title: Lorem Ipsum
    id: "2"
    author_id: "3"
    article_id: "2"
    created_at: 2007-06-16 02:23:40

(Vysvětlení: metoda to_yaml, kterou v uvedených příkladech používáme, je upomínkou další silné zbraně Rails: formátu YAML, tedy „XML pro lidi“: způsobu čitelného zápisu strukturovaných dat. Rails jej využívají jednak pro konfigurace — např. připojení k databázi (/config/database.yml) —, tak pro čitelné výpisy datových struktur — např. pro ladění programu.)

A jak nyní vypadají tabulky (articles, authors, articles_authors) v databázi? Žádné velké překvapení nás nečeká:

mysql> select * from articles;
id title body created_at
2 Lorem Ipsum NULL 0000-00-00 00:00:00
mysql> select * from authors;
id name email
3 Cicero cicero@senatus.gov
mysql> select * from articles_authors;
article_id author_id
2 3

V grafickém vyjádření pak vztahy vypadají takto:

Schéma vztahu has<em>and</em>belongs_to_many

Sloupce v tabulkách articles a authors odpovídají atributům našeho objektu, tabulky jsou na sobě nezávislé. Jejich propojení zajišťuje zvláštní tabulka s názvem articles_authors, která obsahuje dva sloupce pro definici vztahu mezi článkem a autorem: article_id a author_id. To, co vypadá tak logicky, samozřejmě a jednoduše, je samozřejmě výsledkem složité odhadovací logiky v Rails, nikoliv projevem nějaké inteligence stroje. Stroj neví a sám od sebe nemůže vědět, že tabulka s definicemi vztahů se jmenuje articles_authors. To, že nemusíme stroji všechny tyto „logické“ a „samozřejmé“ fakty stále dokola a dokola sdělovat, je výsledkem aplikace několika prostých pravidel:

  1. Deklarace has_and_belongs_to_many v modelech zajistí, že Active Record je bude považovat za propojené a přidá přístupové metody k propojeným objektům, např. ono cicero.articles, použité v příkladu. Has_and_belongs... je poměrně složitý název pro vztah n ku m. Je odvozen z direktiv pro vztah 1 ku n: has_many pro rodičovský objekt („Článek má mnoho komentářů“) a belongs_to („Komentář patří ke článku“) pro jeho děti. Ve vztahu n ku m jsou objekty ve složitějším vztahu: „Článek má mnoho autorů. Autor má mnoho článků.“.

  2. Rails se v takovém případě podívají do databáze, zda najdou tabulku, jejíž název je tvořen názvy tabulek pro dané objekty, oddělené podtržítkem, v abecedním pořádku, tedy: articles_authors. Pokud byste chtěli nebo potřebovali, aby tato tabulka měla jiný název, řekněme authors_to_articles, žádný problém, jde o jednoduchou konfiguraci vztahu v modelu: Class Author ... has_and_belongs_to_many :articles, :join_table => "authors_to_articles".

  3. Tabulka definující vztah pak má dva sloupce: article_id a author_id (každému vztahu odpovídá jeden řádek). I tyto parametry je možné konfigurovat — chceme-li, aby se klíč vztahu jmenoval jinak, není problém: Class Author ... has_and_belongs_to_many :articles, :foreign_key => "clanek_id".

Nejsou v tom tedy žádná kouzla. Kouzla způsobuje lidmi vymyšlený a napsaný kód v hlubinách Rails. Je to ale kód, který vy nemusíte vymýšlet a který vy nemusíte psát. Kouzla jsou způsobena důslednou aplikací principu konvence má přednost před konfigurací v implementaci Active Record. Není důvod konfigurovat název tabulky, je-li v drtivé většině případů utvořen jako množné číslo od názvu třídy. Není důvod konfigurovat tabulku vztahů, jmenuje-li se v drtivé většině případů jako název první tabulky podtržítko název druhé tabulky. Všechna data je třeba na vstupu validovat, proto je ošetření vstupních dat zabudováno přímo v Active Recordu.

To ale není všechno. V běžné webové aplikaci potřebujeme běžně ještě další nástroje na práci s daty: sčítání, výpočty průměrných hodnot, hledání pomocí LIKE, … Active Record v Ruby On Rails nám dává nástrojů mnohem více:

# Kolik článků napsal Cicero?
print cicero.articles.count
=> 1

# Vrať mi články od Cicerona, které začínají na ‚Lor‘ 
cicero = Author.find_by_name('Cicero')
print cicero.articles.find(:all, :conditions => "title LIKE 'Lor%'").to_yaml
=> --- !ruby/object:Article 
   attributes: 
     body: 
     title: Lorem Ipsum
     id: "2"
     author_id: "3"
     article_id: "2"
     created_at: 2007-06-16 02:23:40

Jak je snad z předchozího výkladu o Active Record vidět, Ruby on Rails nejsou „nějaký“ webový framework. Jeho intelektuální úroveň je zcela jedinečná: díky kombinaci promyšlené konfigurace a použití akademických vzorů, jako je Active Record, a zároveň nemilosrdně pragmatického přístupu k vývoji dávají vývojáři do ruky silný nástroj, který nemá jen tak nějaké srovnání.

V dalším článku výklad o Active Record doplníme o možnosti, které mu přidávají pluginy acts_as_attachment a acts_as_list, nejprve se však budeme věnovat zbylým slíbeným bodům.

Komplexní výklad Active Record naleznete v knize Agile Web Development with Rails, doposud nejlepší výukové a zároveň referenční knize o Rails, o níž si někdy také něco povíme.

~


19 komentářů

# 1
jan napsal před rokem:

Diky za skvely clanek. ActiveRecord je urcite moje nejoblibenejsi cast Railsu, alespon z meho pohledu se tam deje nejvic zajimaveho. Delam ted na jedne aplikaci bez databaze a vzhledem k nevyzralosti ActiveResource mi to prvni AR hodne chybi:) Btw sem tam se neco zajimaveho o Railsech v cestine objevi i na http://www.csonrails.net/ At se vam dari i nadale.

# 2
Karel Minařík napsal před rokem:

Díky! :) CSOnRails znovu obživlo, koukám, dlouho jsem tam nebyl, protože se to nějak zastavilo..

V příštím článku bych se chtěl věnovat právě routingu, views, konzoli, apod. pro Rails hodně specifickým věcem. U mně z features co do oblíbenosti rozhodně vyhrává script/console, to je neuvěřitelná věc. :)

Karel

# 3
karf napsal před rokem:

Články o RoR jsou fajn, sám jej neznám (dělám klasicky v PHP), ale nemohl jsem nezaregistrovat ohromné nadšení, který se kolem něj šíří.

Nicméně, když jsem si chtěl něco málo nastudovat, abych byl v obraze, k mému překvapení jsem nenašel žádnou solidní dokumentaci jazyka Ruby (existuje?). Jen samé hurá-CRUD-tutorialy, nebo zběsilé API na www.rubyonrails.org. Ale základní popis syntaxe nikde. Ta syntaxe se mi (podle ukázek) jakožto céčkaři jeví dost zvláštní a asi bych měl problém se její filosofii přizpůsobit.

K ActiveRecord: je tento pattern natolik robustní, aby si s ním vývojář vystačil ve všech aplikacích? Nemůže se brzy dostat do situace, kdy bude potřebovat složitější ORM a RoR bude v koncích? Nic proti tomu, jen se ptám.

# 4
Karel Minařík napsal před rokem:

@karf Dokumentace k samotnému Ruby je na dost dobré úrovni:

  • Základní je online verze kultovní „Pickaxe Book“, Programming Ruby, to je ale samozřejmě v pravém slova smyslu „vyčerpávající dokumentace“

  • K proniknutí do „mentality“ Ruby je myslím si nejlepší fenomenální dílo Why The Lucky Stiffa, Whys Poignant Guide to Ruby

Sám jsem před Rails programoval asi tři roky v PHP, a ze začátku jsem taky tu syntaxi docela nestíhal, proč je před proměnnou někdy @ a někdy ne?, co jsou symboly (:action => 'neco')?, apod. Taky jsem si říkal, že je to hodně divné. A dneska mi přijde divná céčková syntaxe. =) Rozhodně -- i z toho důvodu -- o tom chci ještě napsat zvláštní článek.

Co se týče Rails, to api.rubyonrails.org je samozřejmě trochu divočina na začátek. Taky mně dost štvalo, že jsou k Rails jen „hurá-CRUD“ tutoriály, jak hezky píšete. :) Zkusím rozhodně na blogu popsat pár věcí, na které jsem jako switcher z PHP narazil. :) Ale pokud vás Rails aspoň trochu zajímají, rozhodně bych investoval peníze do „bible“ Rails vývoje: Agile Web Development With Ruby on Rails. O tom ještě chci taky něco napsat.

Co se týče robustnosti ActiveRecord: pro mně bylo a je vodítko to, že Basecamp, Twitter, Shopify, Cork'd nejsou žádné „webíky“, jsou to dost náročné aplikace. A v Rails jsou napsány. To je (pro mně) daleko silnější než nějaká teoretická argumentace. Samozřejmě je vždycky možnost pomocí find_by_sql psát vlastní SQL. Ale na AR je docela pěkné i to, že člověk přemýšlí o aplikaci objektově, a ne na úrovni „dotazů“.

_Poznámka: Pro komentáře je zapnutý pseudo-markup Markdown, dám sem nějakou mininápovědu, jakmile to půjde. _

# 5
Pachollini napsal před rokem:

Jen takové rýpnutí na okraj: pro mě je zase trochu vodítko, že BaseCamp je někdy zoufale pomalý. A co jiného už by mělo šlapat než úspěšná služba od 37signals? BTW. Bavil jsem se s jedním kámošem o rychlosti Rails na webu a pochopil, že to je zatím nevyřešený problém a možná jedna z věcí, která brání skutečně širokému nasazení. Škoda, že se nedostanu do Ostravy, zrovna se kryje s konferencí o subjektu…

# 6
Vladimir Galajda napsal před rokem:

To "zbesile" API na api.rubyonrails.org je mozno pre zaciatocnika naozaj chaoticke, ale pokial preniknete trosku hlbsie do RoR zistite, ze je neocenitelne a velmi rychlo v nom najdete vsetky potrebne informacie ( teda takmer vsetky :-) ).

ActiveRecord je vseobecne znamy ORM vzor a popisuje ho aj Martin Fowler vo svojej knihe Patterns of Enterprise Application Architecture. Treba vsak hned dodat, ze implementacia AR v RoR je znacne rozsirena a pridava nove vlastnosti ako napriklad vazby, dedenie, kolekcie. Tym sa odstranili najvacsie nedostatky tohoto navrhoveho vzoru. Urcite sa najdu pripady, kedy by bolo vhodnejsie pouzit iny pristup. Zatial vsak myslim nikto nenarazil na problem, ktory by neslo vyriesit. Ako Karel pise, su tu uz hotove aplikacie, ktore funguju s AR a stale sa vyvyjaju dalsie.

Len pre uplnost dodam, ze nikto Vas nenuti pouzivat AR pre svoje modely. Mozete pouzit vlastne riesenie ORM a dokonca ak ma pamat neklame, su tu uz take pokusy vytvorit konkurenciu pre AR.

# 7
Vladimir Galajda napsal před rokem:

Ja by som tu rychlost tragicky nevidel. "Pomalost" Ruby je vseobecne znama a pracuje sa na viacerych rieseniach. Ci uz YARV aka Ruby2.0 alebo dalsie implementacie jazyka Ruby. Treba len chvilku vydrzat :-).

Aj v pripade RoR su zname najpomalsie casti ( napr. routing, views ) a su uz dostupne riesenia alebo postupy ako eliminovat "pomalost". Zaujmavo vyzera projekt Erubis, ktory udava znacne zrychlenie oproti standardne pouzivanemu ERB.

Hlavne vsak nesmieme zabudat na osvedcenu hlasku. Vyvojari su drahi, zelezo je lacne. A tu je hlavna vyhoda RoR, ktora predci aj tu pomalost :-).

# 8
Jakub Vrána napsal před rokem:

Díky za článek, s chutí jsem si ho přečetl. Jen bych chtěl upozornit na jeden překlep - v obrázku je uvedeno articles_to_authors, jinde v textu se ale mluví o articles_authors.

# 9
karf napsal před rokem:

karel: díky za informace, Pickaxe Book vypadá dobře. Nemyslím si, že bych začal psát v RoR, ale pro rozšíření obzorů dobré.

Basecamp používáme ve firmě denně, je trochu línější, to je fakt. Ale spíš mi tento systém nepřijde nijak zvlášť excelentní co se týče přehlednosti a ergonomie (na to jak je vychvalován). Ale spoustě lidí asi ano. Myslím, že mají dobrý marketing, hodně lidí je z něj nadšeno už jen proto, že je to přeci ten slavný Basecamp. Ale jinak to není zas tak složitá aplikace.

Vladimir: já jsem právě nabyl dojmu, že AR je tam tak nějak zadrátován, pokud ne, tak to je fajn. Jinak o RoR vím dost málo na to, abych o tomto mohl diskutovat, takže taky díky za informace ;)

# 10
Vladimir Galajda napsal před rokem:

karf: no podla mna je na Basecamp-e dobre prave to, ze je jednoduchy. Su komplikovanejsie alikacie, co ponukaju daleko viacej moznosti. Vtip je prave v tom, ze vacsina ludi si vystaci s tym malom co ponuka Basecamp a nepotrebuju vlastnosti x a y, ktore ich len matu.

S tym AR je to trosku komplikovanejsie. Nemusite ho pouzivat ale uplne odstranit sa neda, lebo niektore casti RoR su zavisle na AR. Vo verzii 1.2.4 by mal byt zacleneny patch, ktory umozni pouzivat RoR bez databazy, odstranenim suboru config/database.yml. Spominany patch http://dev.rubyonrails.org/ticket/7949

# 11
Karel Minařík napsal před rokem:

@Pachollini

Rychlost je důležité téma! :) Rychlost nebo pomalost Basecampu může být dána spoustou faktorů, já před časem zkoušel hosting u Textdrive a odezva jen na ping byla 200ms a klidně více. Takže je otázka, kde „po cestě“ to může nabrat zpoždění. Sám Basecamp na denní bázi nepoužívám, takže to neposoudím.

Co se týče tématu rychlosti samotné, to je spojené s tematikou *výkonnosti a tam měla komunita okolo Rails nedávno krásnou a docela brutální roztržku, koukněte sami. Ve zkratce šlo o to, že chlapci z Twitter vyškálovali servery s Mongrely až na půdu, ale zapoměnli na databázi, a ta se jim pak sesypala, aspoň jak já to pochopil. Takže je to spojené s otázkou škálování.

Jak přesně napsal Vladimir, Rails jsou psány z toho pohledu, že je důležité šetřit programátory a nikoliv stroje. To je ta efektivita měřená počtem úderů do klávesnice z článku. Zde se otevírá skutečná propast v mentalitě mezi vývojem v USA a u nás či dál na východ. V debatách ohledně výkonu pravidelně padá „tak si kup další server a neřeš to, řeš důležitější věci“. U nás pořád ještě by programátor šel a snad psal nějaký optimalizovaný ovladač na něco. :)

V Rails se neřeší spousta takových věcí. Udělejte si jednoduchou aplikaci a pusťe si index page. Těch SQL dotazů co uvidíte, z toho se vám zatočí hlava, jako PHP programátorovi zvyklému pyšnit se tím, jak vytuněný dotaz jste napsali. Rails jsou postavené jinak -- to bude ještě zřejmé z dokončení tohoto úvodu, doufám

Že by to ale „rychlost Rails na webu“ byla nevyřešený problém a bránila jejich rozšíření je ale smělé tvrzení. :) Docela by mně zajímala nějaká argumentace či fakta pro toto tvrzení. (Ať už pro to, že Rails jsou „pomalé“ či pro to, že něco brání jejich rozšíření ;)

Jinak sám Matz se mnohokrát k tématu rychlosti vracel, a vždy říká: je-li to pomalé, zkompilujte si ten kód, proboha. Úplně stejnou odpověď můžeme dát ve světě Rails: nakešujte to, proboha! (Rails disponují promyšleným a transparentním kešovacím systémem.

@Jakub

Díky, opraveno!

@karf

Přesně jak říká Vladimír, AR je do Rails dost integrovaný. A upřímně, moc mně nenapadá důvod, proč ho v Rails nemít. Samozřejmě můžu mít v aplikaci model, který ActiveRecord vůbec nepoužívá, není z něj zděděný -- třeba já mám takový model na www.karmi.cz pro ty Deli.cio.us vpravo, ten si jen periodicky ukládá feed s daty na disk a obnovuje ho. Databázi nepotřebuje, tak ji nemá. =)

# 12
Pachollini napsal před rokem:

Karle, já s Tebou úplně souhlasím, že je snazší / levnější / efektivnější … koupit dalších 6 serverů než sehnat jednoho dobrého vývojáře. Leč na druhé straně, když chceš dělat aplikaci pod opravdu velkou zátěží, můžeš narazit na to, že budeš nejdřív muset postavit další blok Temelína…

Já ty argumenty nejsem schopen reprodukovat, ale bavili jsme se o problematice vytvoření free hostingu pro RoR (u nás AFAIK 00nic) a vypadalo to, že problém je právě s výkonem a správou prostředků. Ale fakt o tom nic nevím.

Nicméně i Vladimír Gajada výše píše, že „se pracuje na více řešeních“. To je IMHO dost vypovídající.

# 13
Karel Minařík napsal před rokem:

Jasně, Matěji, sorry za možná zbytečný důraz. :) Ono hlavně to „snazší/levnější/efektivnější“ platí daleko víc třeba v USA než u nás. Rozhodně máš pravdu, že když budeš počítat s nějakou nestandardní zátěží, máš úplně jiná kritéria pro rozhodování, než když budeš plánovat „konečně svoji“ webovou aplikaci nebo běžný prezentační web.

Tyhle debaty se samozřejmě v Rails komunitě dost vedou — je úplně relevantní zpochybňovat výkon Ruby, Rails, Mongrelu, atd. Většinou je odpověď core vývojářů nebo přímo DHH, že škálovat se má teprve *až* je to potřeba, ne na základě nějaké imaginace o tom, že „by to nemuselo stačit“. :) Někde jsem četl hezké diktum: Vaše aplikace nebude populární jako Flickr od prvního dne. Až bude populární jako Flickr, budete mít úplně jiné problémy. Tak je teď neřešte. To se mi docela líbilo. :)

Ohledně výkonu a škálování je docela poučná ta kontroverze ohledně Twitteru.

Co se týče free-hostingu s Rails, tak to je téma samo o sobě. :) Kdo někdy viděl, kolik MB RAM sežere Mongrel, okamžitě pochopil, proč to nikdo ještě neudělal nikde na světě. :) Připočítej problémy s tím, že by se musely rozdávat SSH přístupy jak na běžícím pásu atd. — takže s Rails free-hostingem je to (zatím?) přesně tak, jak píšeš. =)

Karel

# 14
Botanicus napsal před rokem:

Výborně, velmi pěkně napsané :) Těším se na další pokračování :) Už jsi v RSS ;)

# 15
dgx napsal před rokem:

Článků o Ruby a Railsech není nikdy dost, ale pokud jsou navíc psány takto čtivým a chytrým slohem, je to úplné pošušňáníčko :-)

Těším se na pokračování!

# 16
Jan Brašna napsal před rokem:

Nebylo by lepší Texy než Markdown? Přijde mi docela zkouřený (relikt z MT tuším).

# 17
Jozef Benko napsal před rokem:

Pokiaľ ide o „pomalosť“ Basecampu, používam ho denne a vôbec nemám pocit, že by bol pomalý. Rovnako tak Campfire.

# 18
Kamil Svoboda napsal před 7 měsíci:

Skvělé články!!! Opravdu dobře napsané. Moc díky!

Jen malé upozornění - hosting banan.cz nabízí podporu RoR za 75Kč/měsíc!

# 19
karmi napsal před 7 měsíci:

@Kamil Svoboda:

To je vážně skvělé, a kolik jim tam prosím vás běží Rails aplikací? :) Dejte vědět!!



Karel Minařík navrhuje a programuje webové stránky a aplikace s důrazem na čistý design a interaktivitu. Přednáší o web designu na Institutu Digitálních Médií a o Ruby na FF UK. Píše blog o Ruby On Rails, díky němuž ho opět začalo bavit programovat. Žije v Praze se svojí ženou a dvěma dcerkami, které mu to vše umožňují. Můžete mu napsat e-mail.

Karel Minařík is an independent web designer and developer with focus on clean UI and rich interactivity. He lectures on web design at Institut Digitálních Médií and on Ruby at FF UK. He writes blog about Ruby On Rails (in Czech), which re-ignited his passion for programming. He lives in Prague with his wife and two little daughters, who are making it all possible. You can send him an e-mail.

˜