<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Jaros&#322;aw Zabie&#322;&#322;o - BLOG: Tag merb</title>
    <link>http://blog.zabiello.com/articles/tag/merb</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>moje notatki, linki, komentarze</description>
    <item>
      <title>Agile 3 - jednak wyjdzie</title>
      <description>&lt;p&gt;Mimo, &#380;e wcze&#347;niej &lt;span class="caps"&gt;DHH&lt;/span&gt; niezbyt entuzjastycznie wypowiada&#322; si&#281; na temat pisania kolejnej edycji bestseleru &lt;a href="http://helion.pl/ksiazki/agilep.htm"&gt;Agile Web Development in Rails&lt;/a&gt;, to jednak ugi&#261;&#322; si&#281; pod ci&#281;&#380;arem oczekiwa&#324; i trzecie wydanie b&#281;dzie! Ci, co nie chc&#261; czeka&#263;, mog&#261; ju&#380; teraz kupi&#263; &lt;a href="http://pragprog.com/titles/rails3/agile-web-development-with-rails-third-edition"&gt;&lt;span class="caps"&gt;PDF&lt;/span&gt; z wersj&#261;&#160;beta ksi&#261;&#380;ki&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Je&#347;li autorzy b&#281;d&#261; jak zwykle opisywa&#263; wersj&#281; edge, to ksi&#261;&#380;ka powinna opisywa&#263; &lt;a href="http://weblog.rubyonrails.org/2008/4/30/rails-2-1-release-candidate-is-imminent"&gt;maj&#261;cy wkr&#243;tce wyj&#347;&#263; Rails 2.1&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Dobr&#261; wie&#347;ci&#261; jest te&#380; to, &#380;e Ezra Zygmuntowicz, tw&#243;rca konkurencyjnego &lt;a href="http://merbivore.com/"&gt;Merba&lt;/a&gt;) postanowi&#322; ostatnio po&#347;wi&#281;ci&#263; troch&#281; czasu aby &lt;a href="http://brainspl.at/articles/2008/04/25/hey-rails-nice-rack"&gt;ulepszy&#263; kod Rails&#243;w&lt;/a&gt;. Najwyra&#378;niej oba developerzy obu framework&#243;w si&#281; nie zwalczaj&#261; ale chc&#261; ze sob&#261; wsp&#243;&#322;pracowa&#263;. Ezra &lt;a href="http://brainspl.at/articles/2008/04/18/deferred-requests-with-merb-ebb-and-thin"&gt;doda&#322; ostatnio&lt;/a&gt; ciekawy mechanizm do obs&#322;ugi asynchronicznych adapter&#243;w Thin i Ebb, pozwalaj&#261;cy na tworzenie oddzielnego w&#261;tku w wypadku gdy zapytanie jest d&#322;ugie (aby nie blokowa&#322;a si&#281; asynchroniczna p&#281;tla).&lt;/p&gt;</description>
      <pubDate>Thu, 01 May 2008 20:15:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:2fd10714-776e-4b9a-aa15-6483d939307f</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/05/01/agile3</link>
      <category>rails</category>
      <category>merb</category>
    </item>
    <item>
      <title>GitHub oficjalnie</title>
      <description>&lt;p&gt;Po okresie pilota&#380;owym, &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; wystartowa&#322; &lt;a href="http://github.com/blog/40-we-launched"&gt;oficjalnie&lt;/a&gt;. GitHub udost&#281;pnia wygodne zarz&#261;dzanie projektami korzystaj&#261;cymi z &lt;a href="http://git.or.cz/"&gt;Git&amp;#8217;a&lt;/a&gt; &amp;#8211; rozproszonego systemu wersjonowania kodu. Poza opcjami komercyjnymi jest dost&#281;pne &lt;em&gt;darmowe&lt;/em&gt; konto dla projekt&#243;w open source (tzn. nie mo&#380;na w nim trzyma&#263; prywatnych, zamkni&#281;tych repozytori&#243;w, ale poza tym jest w wystarczaj&#261;co funkcjonalne). Na Git&amp;#8217;a migruje coraz wi&#281;cej projekt&#243;w. Poza &lt;a href="http://www.merbivore.com/"&gt;Merbem&lt;/a&gt; i (&lt;a href="http://weblog.rubyonrails.org/2008/4/2/rails-is-moving-from-svn-to-git"&gt;wkr&#243;tce&lt;/a&gt;) &lt;a href="http://rubyonrails.org"&gt;Railsami&lt;/a&gt;, na GitHuba przenios&#322;y si&#281; ju&#380;: &lt;a href="https://github.com/nex3/haml/tree"&gt;Haml&lt;/a&gt;, &lt;a href="https://github.com/ry/ebb/tree"&gt;Ebb&lt;/a&gt;, &lt;a href="https://github.com/wycats/jspec/tree"&gt;JSpec&lt;/a&gt;, &lt;a href="http://github.com/jamis/capistrano/tree/master"&gt;Capistrano&lt;/a&gt;, &lt;a href="https://github.com/sam/dm-core/tree"&gt;DataMapper&lt;/a&gt; itd.&lt;/p&gt;</description>
      <pubDate>Fri, 11 Apr 2008 01:38:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:2e77f8d5-21d8-49cb-86cc-c064818b75e6</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/04/11/github-oficjalnie</link>
      <category>git</category>
      <category>rails</category>
      <category>merb</category>
    </item>
    <item>
      <title>Merb 0.9.2 - szybki start</title>
      <description>&lt;p&gt;&#379;yjemy w czasach prze&#322;adowania informacj&#261;. Wi&#281;kszo&#347;ci ludzi nie chce si&#281; czyta&#263; dok&#322;adnych dokumentacji, czy kilkuset stronicowych ksi&#261;&#380;ek. Nie dziwi&#281; si&#281;, &#380;e Rails spotka&#322; si&#281; z entuzjastycznym przyj&#281;ciem ze strony os&#243;b zm&#281;czonych walk&#261; z konfiguracj&#261; framework&#243;w Javy czy chaosem i nieelegancj&#261; kodu &lt;span class="caps"&gt;PHP&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Merb pokaza&#322; &#380;e mo&#380;na jeszcze pro&#347;ciej i czytelniej ni&#380; zrobiono w Rails. To dobra informacja dla paranoik&#243;w boj&#261;cych si&#281; Rails&#243;w, kt&#243;rzy chc&#261; czego&#347; bardzo prostego, aby nie musie&#263; korzysta&#263; z &lt;span class="caps"&gt;PHP&lt;/span&gt;. I tu okazuje si&#281;, &#380;e Merb potrafi stworzy&#263; sprawnie dzia&#322;aj&#261;cy projekt pro&#347;ciej (i czytelniej) ni&#380; przyk&#322;ad u&#380;ycia serwletu dost&#281;pny na &lt;a href="http://www.webrick.org/#example"&gt;stronie domowej Webricka&lt;/a&gt;. Merb jest te&#380; o wiele prostszy i bardziej intuicyjny ni&#380; pythonowe frameworki Django, Pylons czy TurboGears (nie m&#243;wi&#261;c o pehapowych).&lt;/p&gt;


	&lt;p&gt;Najnowsza wersja stabilna Merba (0.9.2) jest dost&#281;pna normalnie w gemach. (Napisa&#322;em &amp;#8220;stabilna&amp;#8221;, mimo &#380;e formalnie jest to jeszcze wersja developerska, gdy&#380; Ezra Zygmuntowicz uwa&#380;a j&#261; za wystarczaj&#261;co dopracowan&#261; aby m&#243;c u&#380;ywa&#263; do czego&#347; powa&#380;niejszego.) Instalacja jest wi&#281;c standardowa:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;sudo gem install merb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Merb w przeciwie&#324;stwie do Rails, u&#380;ywa jednego skryptu generatora kodu na wszystko &amp;#8211; &lt;code&gt;merb-gen&lt;/code&gt; (Rails u&#380;ywa skryptu &amp;#8220;rails&amp;#8221; oraz dodatkowych generatorow obecnych w katalogu &lt;code&gt;scripts/&lt;/code&gt;). Standardowo mo&#380;na stworzy&#263; trzy rodzaje projekt&#243;w. Pe&#322;ny, okrojony i minimalistyczny.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;merb-gen app pelny
merb-gen app okrojony --flat
merb-gen app minimalny --very-flat&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Zainteresowanym polecam por&#243;wnanie sobie kodu wygenerowanego w ka&#380;dym z trzech przypadk&#243;w. Dla tych, co chcieliby minimum kodu, ostatnia opcja mo&#380;e by&#263; dosy&#263; atrakcyjna.&lt;/p&gt;


	&lt;h2&gt;Projekt minimalny&lt;/h2&gt;


	&lt;p&gt;W wypadku u&#380;ycia opcji &lt;code&gt;--very-flat&lt;/code&gt; zostan&#261; stworzone 2 (s&#322;ownie: dwa) pliki. Jeden to &lt;span class="caps"&gt;README&lt;/span&gt; (z informacj&#261;, &#380;e ca&#322;o&#347;&#263; odpala si&#281; za pomoc&#261; komendy: &lt;code&gt;merb -I minimalny.rb&lt;/code&gt;), a drugi to kod Rubiego z ca&#322;ym frameworkiem. Za&#322;&#243;&#380;my, &#380;e chcemy prosto przekaza&#263; parametry z &lt;span class="caps"&gt;URL&lt;/span&gt; do kontrolera. Wej&#347;cie na stron&#281;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;http://localhost:4000/?a=test&amp;amp;b=tt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

wy&#347;wietli w przegl&#261;darce 
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;Dosta&#322;em parametry: {&amp;quot;a&amp;quot;=&amp;gt;&amp;quot;test&amp;quot;, &amp;quot;b&amp;quot;=&amp;gt;&amp;quot;tt&amp;quot;, &amp;quot;action&amp;quot;=&amp;gt;&amp;quot;index&amp;quot;, &amp;quot;controller&amp;quot;=&amp;gt;&amp;quot;minimalny&amp;quot;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Ca&#322;y kod frameworka sprowadzi si&#281; do jednego pliku:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Router&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;prepare&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;/&lt;/span&gt;&lt;span class="punct"&gt;').&lt;/span&gt;&lt;span class="ident"&gt;to&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:controller&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;minimalny&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;'&lt;/span&gt;&lt;span class="string"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Minimalny&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Controller&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;index&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dosta&#322;em parametry: &lt;span class="expr"&gt;#{params.inspect}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Config&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;use&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="ident"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:framework&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;           &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{},&lt;/span&gt;
  &lt;span class="ident"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:session_store&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;       &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;none&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
  &lt;span class="ident"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:exception_details&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;   &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W praktyce oczywi&#347;cie wygodniej jest u&#380;ywa&#263; pe&#322;nego projektu, bo daje wygodny dost&#281;p do &lt;span class="caps"&gt;ORM&lt;/span&gt;, szablon&#243;w i wszystkich mo&#380;liwo&#347;ci jakie oferuje Merb.&lt;/p&gt;


	&lt;h2&gt;Projekt pe&#322;ny &amp;#8211; szybki start&lt;/h2&gt;


	&lt;p&gt;Za&#322;&#243;&#380;my, dla prostoty, &#380;e chcemy jakiej&#347; bardzo prostej metody sk&#322;adowania danych i nie chcemy korzysta&#263; (przynajmniej na pocz&#261;tku) z pe&#322;nych serwer&#243;w takich jak MySQL czy PostgreSQL. Doskona&#322;ym wyborem w takiej sytuacji b&#281;dzie &lt;a href="ttp://www.sqlite.org/"&gt;SQLite&lt;/a&gt;. Baza sprowadza si&#281; do jednego pliku, jest szybka i umo&#380;liwia korzystanie z j&#281;zyka &lt;span class="caps"&gt;SQL&lt;/span&gt; (w&#322;&#261;cznie z transakcjami). Instaluje si&#281; j&#261; z gemow:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;sudo gem install sqlite3-ruby&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Tworzymy projekt:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;merb-gen app myproj&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Zostanie stworzony katalog myproj z r&#243;&#380;nymi plikami i katalogami w &#347;rodku. To jest &lt;strong&gt;szkielet aplikacji&lt;/strong&gt; i jest nawet prostszy od tego co generuj&#261; Rails.&lt;/p&gt;


	&lt;p&gt;Domy&#347;lnie Merb nie zak&#322;ada, &#380;e chcemy korzysta&#263; z baz danych. Aby uaktywni&#263; obs&#322;ug&#281; bazy danych, wejd&#378; do pliku &lt;code&gt;config/init.rb&lt;/code&gt; i odkomentowa&#263; jedn&#261; linijk&#281; z trzech dost&#281;pnych bibliotek zapewniaj&#261;cych obiektowy dost&#281;p do relacyjnej bazy danych: &lt;a href="http://ar.rubyonrails.org/"&gt;Active Record&lt;/a&gt;, &lt;a href="http://datamapper.org/"&gt;DataMapper&lt;/a&gt; lub &lt;a href="http://code.google.com/p/ruby-sequel/"&gt;Sequel&lt;/a&gt;. Za&#322;&#243;&#380;my, &#380;e wybrali&#347;my ten trzeci (m&#243;j ulubiony ze wzgl&#281;du na prostot&#281; i elastyczno&#347;&#263;; oczywi&#347;cie zak&#322;adam, &#380;e wcze&#347;niej zainstalowali&#347;my: &lt;code&gt;sudo gem install sequel&lt;/code&gt;)&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;use_orm&lt;/span&gt; &lt;span class="symbol"&gt;:sequel&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Od tej chwili Merb b&#281;dzie zak&#322;ada&#322;, &#380;e chcemy pracowa&#263; z baz&#261; danych za pomoc&#261; Sequela. To znacznie upro&#347;ci to prac&#281; z sam&#261; baz&#261; SQLite i u&#322;atwi  ewentualne przepi&#281;cie aplikacji ze SQLite do MySQL czy innej bazy. Teraz przejd&#378; do konsoli i odpal w katalogu projektu polecenie:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;merb&lt;/span&gt;&lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="ident"&gt;gen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Merb ju&#380; wie, &#380;e chcesz u&#380;ywa&#263; bazy, wi&#281;c teraz automatycznie stworzy teraz plik konfiguracyjny &lt;code&gt;config/database.sample.yml&lt;/code&gt;. Nale&#380;y zmieni&#263; jego nazw&#281; &lt;code&gt;database.yml&lt;/code&gt;. Domy&#347;lnie tworzone s&#261; tam ustawienia dla MySQL. Aby u&#380;y&#263; SQLite, zmie&#324; go na:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_yaml "&gt;&lt;span class="document"&gt;---
:development: &amp;amp;defaults&lt;/span&gt;
  &lt;span class="symbol"&gt;:adapter&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; sqlite
  &lt;span class="symbol"&gt;:database&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; baza.db
  &lt;span class="symbol"&gt;:encoding&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; utf8

:test:
  &amp;lt;&amp;lt;: *defaults
  &lt;span class="symbol"&gt;:database&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; baza-testowa.db

:production:
  &amp;lt;&amp;lt;: *defaults&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Teraz stworzmy jaki&#347; przyk&#322;adowy model danych z u&#380;ytkownikami i kontroler do ich zarz&#261;dzania. Stw&#243;rzmy od razu ca&#322;y zas&#243;b z obs&#322;ug&#261; &lt;span class="caps"&gt;REST&lt;/span&gt;.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;merb-gen resource user&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Teraz przejd&#378; do pliku schema/migrations/001_user.rb  i zmie&#324; go na&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;UserMigration&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Sequel&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Migration&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;up&lt;/span&gt;
    &lt;span class="ident"&gt;create_table&lt;/span&gt; &lt;span class="symbol"&gt;:users&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;varchar&lt;/span&gt; &lt;span class="symbol"&gt;:name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:unique&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;
      &lt;span class="ident"&gt;primary_key&lt;/span&gt; &lt;span class="symbol"&gt;:id&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;down&lt;/span&gt;
    &lt;span class="ident"&gt;execute&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;DROP TABLE users&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 

	&lt;p&gt;B&#281;d&#261;c w katalogu projektu, odpal polecenie: uruchamiaj&#261;ce &amp;#8220;proces migracji:http://code.google.com/p/ruby-sequel/wiki/Migrations:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;rake sequel:db:migrate&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 

	&lt;p&gt;Zostanie stworzona baza (plik: baza.db) oraz tabela users. No to teraz troch&#281; si&#281; pobawmy interaktywn&#261; konsol&#261; aby doda&#263; jakie&#347; dane do bazy.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="global"&gt;$ &lt;/span&gt;&lt;span class="ident"&gt;merb&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;
 ~ &lt;span class="constant"&gt;Loaded&lt;/span&gt; &lt;span class="constant"&gt;DEVELOPMENT&lt;/span&gt; &lt;span class="constant"&gt;Environment&lt;/span&gt;&lt;span class="punct"&gt;...&lt;/span&gt;
 ~ &lt;span class="ident"&gt;loading&lt;/span&gt; &lt;span class="ident"&gt;gem&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;merb_sequel&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="ident"&gt;from&lt;/span&gt;  &lt;span class="punct"&gt;...&lt;/span&gt;
 ~ &lt;span class="constant"&gt;Connecting&lt;/span&gt; &lt;span class="ident"&gt;to&lt;/span&gt; &lt;span class="ident"&gt;the&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;baza.db&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="ident"&gt;database&lt;/span&gt; &lt;span class="ident"&gt;on&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="ident"&gt;using&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;sqlite&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;...&lt;/span&gt;
 ~ &lt;span class="constant"&gt;Compiling&lt;/span&gt; &lt;span class="ident"&gt;routes&lt;/span&gt;&lt;span class="punct"&gt;...&lt;/span&gt;
 ~ &lt;span class="constant"&gt;Using&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;share-nothing&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="ident"&gt;cookie&lt;/span&gt; &lt;span class="ident"&gt;sessions&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;4&lt;/span&gt;&lt;span class="ident"&gt;kb&lt;/span&gt; &lt;span class="ident"&gt;limit&lt;/span&gt; &lt;span class="ident"&gt;per&lt;/span&gt; &lt;span class="ident"&gt;client&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;create&lt;/span&gt; &lt;span class="symbol"&gt;:name&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Jarek&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="comment"&gt;#&amp;lt;User @values={:name=&amp;gt;&amp;quot;Jarek&amp;quot;, :id=&amp;gt;1}&amp;gt;&lt;/span&gt;
&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;create&lt;/span&gt; &lt;span class="symbol"&gt;:name&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Ewa&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="comment"&gt;#&amp;lt;User @values={:name=&amp;gt;&amp;quot;Ewa&amp;quot;, :id=&amp;gt;2}&amp;gt;&lt;/span&gt;
&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;all&lt;/span&gt;
&lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="comment"&gt;#&amp;lt;User @values={:name=&amp;gt;&amp;quot;Jarek&amp;quot;, :id=&amp;gt;1}&amp;gt;, #&amp;lt;User @values={:name=&amp;gt;&amp;quot;Ewa&amp;quot;, :id=&amp;gt;2}&amp;gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 

	&lt;p&gt;OK. Ostatni krok. Otw&#243;rz plik &lt;code&gt;app/views/users/index.html.erb&lt;/code&gt; i wstaw:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_rhtml "&gt;&amp;lt;p&amp;gt;W bazie mam u&#380;ytkownik&#243;w o imionach:&amp;lt;/h1&amp;gt;
&amp;lt;% for user in @users %&amp;gt;
  &amp;lt;p&amp;gt;&amp;lt;%= user.name %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 

	&lt;p&gt;To wszystko! Odpal serwer z aplikacj&#261; za pomoc&#261; komendy: &lt;code&gt;merb&lt;/code&gt;
(wi&#281;cej: &lt;code&gt;merb --help&lt;/code&gt;) i otw&#243;rz stron&#281; http://localhost:4000/users&lt;/p&gt;


	&lt;h2&gt;Dodatkowe informacje&lt;/h2&gt;


	&lt;p&gt;Ezra Zygmuntowicz zapowiedzia&#322; intensywne prace nad stworzeniem zestawu manuali i dodatkowej dokumentacji dla Merba. Na razie musi wystarczy&#263; to, co jest dost&#281;pne na &lt;a href="http://merbivore.com/documentation.html"&gt;stronie projektu&lt;/a&gt; plus informacje dost&#281;pne w blogach i na kanale &lt;span class="caps"&gt;IRC&lt;/span&gt; &lt;a href="irc://irc.eu.freenode.net/merb"&gt;#merb&lt;/a&gt; serwera freenode.net. &lt;a href="http://peepcode.com/products/meet-merb-pdf-draft"&gt;Powstaje te&#380; ksi&#261;&#380;ka&lt;/a&gt; kt&#243;ra jest dost&#281;pna w wersji roboczej przez PeepCode. &lt;a href="http://merbivore.com/documentation.html"&gt;&lt;span class="caps"&gt;API&lt;/span&gt; Merba&lt;/a&gt; jest dosy&#263; przejrzy&#347;cie opisane i co wa&#380;niejsze, przyj&#281;to &#347;cis&#322;e &lt;a href="http://merbivore.com/contribute.html"&gt;zasady tworzenia dokumentacji&lt;/a&gt;, kt&#243;ra by&#322;y opisane wszystkie mo&#380;liwe parametry dla ka&#380;dej metody plus jaki&#347; przyk&#322;ad u&#380;ycia.&lt;/p&gt;</description>
      <pubDate>Mon, 31 Mar 2008 01:09:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:7ff92e90-078e-4d96-94cf-0a097bf808e4</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/03/31/merb092-start</link>
      <category>merb</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Wzmacnianie ekosystemu Rubiego - Merb</title>
      <description>&lt;p&gt;Przedwczoraj, w ramach &lt;a href="http://mtnwestrubyconf.org/"&gt;MountainWest Ruby Conference 2008&lt;/a&gt;, mia&#322;o miejsce ciekawe wyst&#261;pienie Ezry Zygmuntowicza na temat &lt;a href="http://merbivore.com/"&gt;Merba&lt;/a&gt;, webowego frameworka stworzonego w j&#281;zyku Ruby. Wersja strumieniowa, pliki wideo oraz slajdy z wyk&#322;adu, &lt;a href="http://mtnwestrubyconf2008.confreaks.com/02zygmuntowicz.html"&gt;s&#261; do pobrania&lt;/a&gt; w internecie. Ezra w prosty spos&#243;b pokaza&#322; kilka interesuj&#261;cych cech Merba, kt&#243;re odr&#243;&#380;niaj&#261; go od konkurencyjnego Ruby on Rails.&lt;/p&gt;


	&lt;h2&gt;Prostota jest lepsza od magii&lt;/h2&gt;


	&lt;p&gt;Przede wszystkim, Merb zbudowano na za&#322;o&#380;eniu &#380;e &lt;strong&gt;prostota jest lepsza od magii&lt;/strong&gt;. Wiele os&#243;b nie znaj&#261;cych zbytnio Rubiego, kt&#243;re zetkn&#281;&#322;y si&#281; z Railsami, my&#347;l&#261;, &#380;e permanentnie magiczne (implicite) podej&#347;cie do kodowania do jaka&#347; integralna cz&#281;&#347;&#263; samego j&#281;zyka Ruby. Tymczasem to nie jest problem Rubiego, ale filozofii zastosowanej w Rails. Sam Ruby (z za&#322;o&#380;enia) pozwala na rozwi&#261;zanie tego samego problemu na bardzo wiele sposobow. W pe&#322;ni zgadzam si&#281; z Ezr&#261;, &#380;e operowanie na otwartych klasach Rubiego mo&#380;e by&#263; bardzo u&#380;yteczn&#261; technik&#261;, ale z drugiej strony, nie powinna to by&#263;  g&#322;&#243;wna, ani najwa&#380;niejsza, technika w arsenale narz&#281;dzi programisty Rubiego. W ostatecznym rozrachunku, &#322;atwiej wr&#243;ci&#263; do kodu kt&#243;ry jest prosty ni&#380; tylko &#322;adny i magiczny z implementacj&#261; zaszyt&#261; g&#322;&#281;boko w gdzie&#347; includowanej bibliotece.&lt;/p&gt;


	&lt;p&gt;Ale Merb na tym si&#281; nie zatrzymuje. Jego mottem przewodnim jest &lt;strong&gt;nie ma szybszego kodu od braku kodu&lt;/strong&gt;. Ezra nie zgadza si&#281; za bardzo z rozumowaniem prezentowanym przez &lt;span class="caps"&gt;DHH&lt;/span&gt; i Rails, &#380;e skoro czas programisty jest dro&#380;szy od czasu serwera, to kto martwi si&#281; o wydajno&#347;&#263;, niech sobie dostawi&amp;#8230; wi&#281;cej serwer&#243;w. Nawi&#261;zuje to do permanentnie b&#322;&#281;dnej polityki ignorowania optymalizacji wydajno&#347;ciowej w Rails na rzecz koncentrowania si&#281; na ci&#261;gle nowej funkcjonalno&#347;ci, &amp;#8220;a wydajno&#347;&#263; poprawi si&#281; p&#243;&#378;niej, lub dostawi wi&#281;cej sprz&#281;tu&amp;#8221;. To prawda, &#380;e &amp;#8220;przedwczesna optymalizacja jest korzeniem wielu problem&#243;w, komplikacji itp. itd&amp;#8221; Prawd&#261; jest jednak&#380;e i to, &#380;e &amp;#8220;zbyt p&#243;&#378;na optymalizacja jest korzeniem wszystkich dodatkowych faktur do zap&#322;acenia dla centrum hostingowego&amp;#8221;. Merb od pocz&#261;tku jest tworzony z uwzgl&#281;dnieniem wydajno&#347;ci, modularno&#347;ci, wielow&#261;tkowo&#347;ci i elastyczno&#347;ci.&lt;/p&gt;


	&lt;p&gt;Merb (licz&#261;c od wersji 0.9 kt&#243;ra wnosi ogromne zmiany do wcze&#347;niejszej 0.5.x) zosta&#322; podzielony na kilka modu&#322;&#243;w. Rdze&#324; frameworka znajduje si&#281; w &lt;code&gt;merb-core&lt;/code&gt;. Dodatkowe mo&#380;liwo&#347;ci s&#261; dost&#281;pne w &lt;code&gt;merb-more&lt;/code&gt; i &lt;code&gt;merb-plugins&lt;/code&gt;. Nowy Merb jest zbudowany te&#380; na fundamenci&#281; &lt;a href="http://rack.rubyforge.org/"&gt;Rack&amp;#8217;a&lt;/a&gt; (wzorowanego na pythonowym &lt;a href="http://www.python.org/dev/peps/pep-0333/"&gt;&lt;span class="caps"&gt;WSGI&lt;/span&gt;&lt;/a&gt;, interfejsie dla aplikacji korzystaj&#261;cych z protoko&#322;u &lt;span class="caps"&gt;HTTP&lt;/span&gt;). Merb mo&#380;e by&#263; uruchamiany z kilkoma serwerami: Ebb, asynchroniczny Mongrel (Evented Mongrel), FastCGI, wielow&#261;tkowy Mongrel (Merb, w przeciwie&#324;stwie do Rails, jest w pe&#322;ni wielow&#261;tkowy), Thin czy Webrick.&lt;/p&gt;


	&lt;h2&gt;Wielow&#261;tkowo czy asynchronicznie?&lt;/h2&gt;


	&lt;p&gt;Ezra zwr&#243;ci&#322; uwag&#281; na dosy&#263; istotny aspekt wydajno&#347;ci dla adappterami asynchronicznymi (Ebb, Evented Mongrel, Thin) a wielow&#261;tkowym Mongrelem. Ot&#243;&#380; nie zawsze adaptery asynchroniczne s&#261; szybsze. Tak jest tylko w wypadku kr&#243;tko trwaj&#261;cych zapyta&#324;. Jednak&#380;e je&#347;li mamy sytuacj&#281; obs&#322;ugi jakiego&#347; d&#322;ugiego (kilku sekundowego) requestu, to adapter asynchroniczny ma zablokowan&#261; p&#281;tl&#281; i w efekcie, jak to okre&#347;li&#322; Erza, &amp;#8220;pada na pysk&amp;#8221;. Wielow&#261;tkowy Mongrel w takiej sytuacji, nie blokuje swojej pracy, ale odpala kolejny w&#261;tek dla obs&#322;ugi nast&#281;pnych request&#243;w. To, wi&#281;c, co warto u&#380;y&#263; zale&#380;y od charakteru aplikacji i mo&#380;na powiedzie&#263; &#380;e wielow&#261;tkowy Mongrel jest najbardziej uniwersalnym, cho&#263; nie zawsze najszybszym, rozwi&#261;zaniem. Mo&#380;na ewentualnie miesza&#263; podej&#347;cia i oczekiwane jako wolne, requesty kierowa&#263; na Mongrela a reszt&#281; na Ebb, czy Thin.  Osobi&#347;cie tego jeszcze nie testowa&#322;em, ale wydaje si&#281; to rozs&#261;dnym podej&#347;ciem.&lt;/p&gt;


	&lt;h2&gt;Pot&#281;&#380;niejszy router adres&#243;w&lt;/h2&gt;


	&lt;p&gt;Merb ma kompletnie inaczej napisany resolver adres&#243;w &lt;span class="caps"&gt;URL&lt;/span&gt; ni&#380; Rails. Po pierwsze, jest du&#380;o szybszy ze wzgl&#281;duna stosowan&#261; prekompilacj&#281;. Po drugie, jest du&#380;o elastyczniejszy od Rails&#243;w (czy Django, gdzie kt&#243;ry jest r&#243;wnie s&#322;aby). Przyjrzyjmy si&#281; poni&#380;szemu przyk&#322;adowi.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Router&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;prepare&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;(%r[&lt;/span&gt;&lt;span class="regex"&gt;^/foor(.+)&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="symbol"&gt;:user_agent&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;(MSIE|Gecko)&lt;/span&gt;&lt;span class="punct"&gt;/).&lt;/span&gt;
    &lt;span class="ident"&gt;to&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:controller&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;foo&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="symbol"&gt;:title&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;[1]&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;),&lt;/span&gt;
       &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;show&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="symbol"&gt;:agent&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;:user_agent[1]&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;

  &lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/bar/:baz&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;defer_to&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;bar&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Bar&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find_by_baz&lt;/span&gt; &lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:baz&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
      &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:controller&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;bar&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;controller&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
        &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;bar&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;action&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
        &lt;span class="symbol"&gt;:bar&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;bar&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_param&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W regule pierwszej wida&#263;, &#380;e router adres&#243;w zastosowany w Merbie pozwala filtrowa&#263; po dowolnych nag&#322;&#243;wkach. Np. mo&#380;e wiedzie&#263; czy u&#380;yto przegl&#261;darki Internet Explorer czy Firefox i stosownie do tego podejmuje dalsze dzia&#322;ania. Drugi przyk&#322;ad jest jeszcze ciekawszy. Z adresu &lt;span class="caps"&gt;URL&lt;/span&gt; wy&#322;uskiwana jest warto&#347;&#263; kt&#243;r&#261; Merb wykorzystuje aby odpyta&#263; baz&#281; danych i na tej podstawie odpowiednio przekierowa&#263; sterowanie.&lt;/p&gt;


	&lt;h2&gt;Akcje o sk&#322;adni metod Rubiego&lt;/h2&gt;


	&lt;p&gt;Mimo, &#380;e Merb pozwala, w podobny (do Rails) spos&#243;b, korzysta&#263; z hasza &lt;code&gt;params&lt;/code&gt;, dodano tu troch&#281; syntaktycznego lukru pozwalaj&#261;cego na pisanie kodu akcji w kontrolerze tak jak si&#281; pisze zwyk&#322;e metody w Rubim.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add_mime_type&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:yaml&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:to_yaml&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;application/x-yaml text/yaml&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add_mime_type&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:text&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:to_text&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;text/plain&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add_mime_type&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:html&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:to_html&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;text/html application/xhtml+xml application/html&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add_mime_type&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:xml&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;  &lt;span class="symbol"&gt;:to_xml&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;  &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;application/xml text/xml application/x-xml&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="symbol"&gt;:Encoding&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;UTF-8&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add_mime_type&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:js&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;   &lt;span class="symbol"&gt;:to_json&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;text/javascript application/javascript application/x-javascript&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add_mime_type&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:json&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:to_json&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;application/json text/x-json&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;      
&lt;span class="comment"&gt;#...&lt;/span&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Posts&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Application&lt;/span&gt;
  &lt;span class="ident"&gt;provides&lt;/span&gt; &lt;span class="symbol"&gt;:json&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:yaml&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:xml&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;show&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@post&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt; &lt;span class="ident"&gt;id&lt;/span&gt;
    &lt;span class="ident"&gt;display&lt;/span&gt; &lt;span class="attribute"&gt;@post&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Jarek&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="ident"&gt;only_provides&lt;/span&gt; &lt;span class="symbol"&gt;:html&lt;/span&gt;
    &lt;span class="attribute"&gt;@user&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find_by_name&lt;/span&gt; &lt;span class="ident"&gt;name&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Przekazywanie parametr&#243;w w metodzie zamiast w haszu, moim zdaniem, znacznie zwi&#281;ksza czytelno&#347;&#263; kodu. Umo&#380;liwia te&#380; wygodne stosowanie warto&#347;ci domy&#347;lnych.&lt;/p&gt;


	&lt;p&gt;S&#322;owo wyja&#347;nienia nale&#380;y si&#281; metodzie display(). Merb w inny (od Rails) spos&#243;b rozpoznaje typ &lt;span class="caps"&gt;MIME&lt;/span&gt; przekazany do metody. Zamiast przekazywa&#263; w akcji blok do respond_to, Merb definiuje tylko jakie metody maj&#261; by&#263; wywo&#322;ane dla odpowiedniego &lt;span class="caps"&gt;MIME&lt;/span&gt;.  Np. akcja odpalana dla adresu &lt;code&gt;/posts/user&lt;/code&gt; przekazuje do metody &lt;code&gt;user&lt;/code&gt; hasz params o warto&#347;ci &lt;code&gt;{:name =&amp;gt; "Jarek"}&lt;/code&gt;. Pobiera rekord z bazy i zwraca do klienta kod &lt;span class="caps"&gt;HTML&lt;/span&gt; wywo&#322;any za pomoc&#261; metody &lt;code&gt;to_html&lt;/code&gt; na obiekcie &lt;code&gt;user&lt;/code&gt;. W wypadku metody &lt;code&gt;show&lt;/code&gt; zwracanych jest wiele r&#243;&#380;nych reprezentacji zale&#380;nych od u&#380;ytego &lt;span class="caps"&gt;MIME&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Trzeba te&#380; doda&#263;, &#380;e Merb nie u&#380;ywa &#380;adnych magicznych railsowych metod &lt;code&gt;render&lt;/code&gt; kt&#243;re mog&#261; by&#263; wywo&#322;ane tylko jeden raz (sic!) na request. Merb mo&#380;e kolekcjonowa&#263; output z kilku miejsc. Za&#347; je&#347;li chodzi o sam&#261; akcj&#281; kontrolera, to zwracane jest po prostu ostatnie wyra&#380;enie (tak, jak w zwyk&#322;ych metodach Rubiego). Np. mo&#380;na otworzy&#263;&#160;plik i zwr&#243;ci&#263; stworzony obiekt &lt;code&gt;IO&lt;/code&gt; w metodzie kontrolera, a Merb potraktuje to jako przesy&#322;anie &lt;strong&gt;strumieniowe&lt;/strong&gt;.&lt;/p&gt;


	&lt;h2&gt;Git rz&#261;dzi&lt;/h2&gt;


	&lt;p&gt;Ezra podkre&#347;li&#322; sporo korzy&#347;ci jakie da&#322;o przej&#347;cie na rozproszony system wersjonowania kodu (Git). Znacznie &#322;atwiej mo&#380;na eksperymentowa&#263; z kodem i zg&#322;asza&#263; poprawki ni&#380; w wypadku starego &lt;span class="caps"&gt;SVN&lt;/span&gt;&amp;#8217;a. I co ciekawe, tak&#380;e Ruby on Rails zamierza te&#380; przej&#347;&#263; na Git&amp;#8217;a w przeci&#261;gu jakich&#347; dw&#243;ch miesi&#281;cu.&lt;/p&gt;</description>
      <pubDate>Sun, 30 Mar 2008 20:39:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:a9c11a35-7d21-40bf-8df1-207344596196</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/03/30/rubyconf2008-merb</link>
      <category>ruby</category>
      <category>merb</category>
      <category>rails</category>
    </item>
    <item>
      <title>Merb 0.9.2 i Sake</title>
      <description>&lt;p&gt;&lt;a href="http://merbivore.com/"&gt;Merb&lt;/a&gt; wchodzi w ko&#324;cow&#261; faz&#281; przed wydaniem wersji &amp;#8220;1.0 (RailsConf)&amp;#8221; . W&#322;a&#347;ciwie nie zdziwi&#322;bym si&#281; jakby lada dzie&#324; ta wesja wysz&#322;a bo &lt;a href="http://merb.lighthouseapp.com/projects/7435-merb-more/milestones"&gt;prawie wszystkie&lt;/a&gt; tickety z problemami s&#261; ju&#380; wyczyszczone. Rozproszony system wersjonowania kodu &amp;#8211; &lt;a href="http://pl.wikibooks.org/wiki/Git"&gt;Git&lt;/a&gt; &amp;#8211; sprawdza si&#281; doskonale. Rozproszony Rake &amp;#8211; &lt;a href="http://errtheblog.com/posts/60-sake-bomb"&gt;Sake&lt;/a&gt; &amp;#8211; tak&#380;e. Nowy Merb wspiera &lt;a href="http://ebb.rubyforge.org/"&gt;Ebb&lt;/a&gt;. Jest on szybszy od &lt;a href="http://mongrel.rubyforge.org/"&gt;Mongrela&lt;/a&gt;, to najszybszy serwer &lt;span class="caps"&gt;HTTP&lt;/span&gt; dla Rubiego wykorzystuj&#261;cy interfejs &lt;a href="http://rack.rubyforge.org/"&gt;Rack&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Sake&lt;/strong&gt;, to &lt;a href="http://rake.rubyforge.org/"&gt;Rake&lt;/a&gt; tylko, &#380;e dzia&#322;aj&#261;cy zdalnie! Mo&#380;na plik z taskami dla Rake wstawi&#263; gdziekolwiek w internecie i ka&#380;dy mo&#380;e go u&#380;ywa&#263;. Najlepiej zobaczy&#263; to na przyk&#322;adzie.&lt;/p&gt;


	&lt;p&gt;Stworzy&#322;em w Githubie mini projekt &lt;a href="http://github.com/hipertracker/merb-scripts/tree/master"&gt;merb-scripts&lt;/a&gt; gromadz&#261;cym r&#243;&#380;ne wygodne zadania w kontek&#347;cie Merba.&lt;/p&gt;


	&lt;p&gt;Sprawdzenie dost&#281;pnych zada&#324;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;$ sake -T http://blog.zabiello.com/merb-scripts.sake
sake merb:pull         # Pull merb-core, merb-more, merb-plugins
sake merb:uninstall    # Uninstall all Ruby merb* gems
sake merb:juninstall   # Uninstall all JRuby merb* gems
sake merb:repackage    # Repackage merb-&amp;lt;core|more|plugins&amp;gt; (with all subgems)
sake merb:install      # Install all Merb gems and subgems
sake merb:jinstall     # Install all Merb gems and subgems for JRuby&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Dodanie listy zada&#324; do lokalnego repozytorium Sake (dok&#322;adniej: do pliku ~/.sake).&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;sake -i http://blog.zabiello.com/merb-scripts.sake
sake -T # poka&#380; now&#261; list&#281; zada&#324;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Sprawdzenie &#378;r&#243;d&#322;a dla danej komendy:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;sake&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="ident"&gt;e&lt;/span&gt; &lt;span class="ident"&gt;merb&lt;/span&gt;&lt;span class="symbol"&gt;:pull&lt;/span&gt;

&lt;span class="ident"&gt;desc&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Pull merb-core, merb-more, merb-plugins&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;task&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;merb:pull&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="constant"&gt;Rake&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Task&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;merb:init&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;].&lt;/span&gt;&lt;span class="ident"&gt;invoke&lt;/span&gt;
  &lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;merb-core&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;merb-more&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;merb-plugins&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;].&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;dir&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;exists?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;dir&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;then&lt;/span&gt;
      &lt;span class="ident"&gt;sh&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;cd &lt;span class="expr"&gt;#{dir}&lt;/span&gt;; git pull&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt;
      &lt;span class="ident"&gt;sh&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;git clone git://github.com/&lt;span class="expr"&gt;#{@git_fork}&lt;/span&gt;/&lt;span class="expr"&gt;#{dir}&lt;/span&gt;.git&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;&#346;ci&#261;gni&#281;cie najnowszej wersji rozwojowej Merba, kompilacja gem&#243;w i instalacja dla JRuby (musi by&#263; dost&#281;pny w systemie)&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;sake merb:pull merb:repackage merb:jinstall&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Dla tych, co jeszcze nie wiedz&#261;. Jest ju&#380; dost&#281;pny &lt;a href="http://dist.codehaus.org/jruby/"&gt;JRuby &lt;span class="caps"&gt;RC3&lt;/span&gt;&lt;/a&gt; i Merb mo&#380;e by&#263; uruchamiany pod JRuby tak jak i Rails.&lt;/p&gt;</description>
      <pubDate>Tue, 25 Mar 2008 07:11:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:ac3d5ab1-00e0-46d8-903f-ab6320adc8ce</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/03/25/merb092-sake</link>
      <category>rake</category>
      <category>sake</category>
      <category>ruby</category>
      <category>merb</category>
      <category>jruby</category>
    </item>
    <item>
      <title>Szalej&#261;ce frameworki Rubiego i Rack/WSGI</title>
      <description>&lt;p&gt;Merb w wersji 0.9 poszed&#322; na ca&#322;o&#347;&#263; i oparli sw&#243;j midleware na &lt;a href="http://rack.rubyforge.org/"&gt;Rack&amp;#8217;u&lt;/a&gt;. Jej tw&#243;rcy nie kryj&#261; si&#281; &#380;e wzorowali si&#281; na pythonowej bibliotece &lt;a href="http://www.wsgi.org/wsgi"&gt;&lt;span class="caps"&gt;WSGI&lt;/span&gt;&lt;/a&gt;. Biblioteka ta robi niez&#322;&#261; furor&#281; w kr&#281;gach Rubiego. Powstaje sporo r&#243;&#380;nych mikroframework&#243;w lub szybkich serwer&#243;w &lt;span class="caps"&gt;HTTP&lt;/span&gt; pracuj&#261;cych asynchronicznie i wykorzystuj&#261;cych Rack. Niedawno powsta&#322; &#347;wietny &lt;a href="http://code.macournoyer.com/thin/"&gt;Thin&lt;/a&gt;, a ju&#380; mo&#380;na przeczyta&#263; o &lt;a href="http://www.rubyinside.com/ebb-web-framework-http-server-786.html"&gt;2x szybszy Ebb&lt;/a&gt;. Co ciekawe, Ebb chce docelowo obs&#322;ugiwa&#263; zar&#243;wno frameworki Rubiego jak i &lt;strong&gt;Pythona&lt;/strong&gt;! Jestem ciekaw czy b&#281;dzie w stanie zdetronizowa&#263; serwer &lt;a href="http://pythonpaste.org/"&gt;Paste&lt;/a&gt;... Rack doczeka&#322; si&#281; ju&#380; swojej &lt;a href="http://github.com/booleanman/rackinterfacefilter/tree/master"&gt;implementacji w JRuby&lt;/a&gt;! Umo&#380;liwia to  tym samym odpalanie w &lt;a href="http://jruby.codehaus.org/"&gt;JRuby&lt;/a&gt; wszystkich framework&#243;w kt&#243;re korzystaj&#261; z Rack&amp;#8217;a.&lt;/p&gt;


	&lt;h2&gt;Frameworki&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://rubyonrails.pl"&gt;&lt;strong&gt;Rails&lt;/strong&gt;&lt;/a&gt; &amp;#8211; najwa&#380;niejszy framework Rubiego, mo&#380;e by&#263; odpalany za pomoc&#261; Thina kt&#243;ry &lt;em&gt;u&#380;ywa Rack&lt;/em&gt;. Rails mo&#380;na odpali&#263; na JRuby nawet prosto z &lt;a href="http://www.netbeans.org/features/ruby/index.html"&gt;Netbeans 6&lt;/a&gt; :)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://merbivore.com/"&gt;&lt;strong&gt;Merb&lt;/strong&gt;&lt;/a&gt; &amp;#8211; pretendent do detronizacji Rails, _u&#380;ywa Rack_i tym samym mo&#380;na go odpali&#263; na JRuby.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://ramaze.net/"&gt;Ramaze&lt;/a&gt; &amp;#8211; podobnie do Merba, stara si&#281; promowa&#263; bardziek elastyczne podej&#347;cie, &lt;em&gt;u&#380;ywa Rack&lt;/em&gt;, raczej nie zagrozi Merbowi&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://fuzed.rubyforge.org/"&gt;Fuzed&lt;/a&gt; &amp;#8211; Rails z &lt;a href="http://yaws.hyber.org/"&gt;&lt;span class="caps"&gt;YAWS&lt;/span&gt;&lt;/a&gt; (szybkim serwerem &lt;span class="caps"&gt;HTTP&lt;/span&gt; napisanym w &lt;a href="http://en.wikipedia.org/wiki/Erlang_programming_language"&gt;Erlangu&lt;/a&gt;)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.nitroproject.org/"&gt;Nitro&lt;/a&gt; &amp;#8211; typu &lt;span class="caps"&gt;MVC&lt;/span&gt; z w&#322;asnym &lt;span class="caps"&gt;ORM&lt;/span&gt; &amp;#8211; &lt;a href="http://www.nitroproject.org/docs/rdoc/classes/Og.html"&gt;Ogg&lt;/a&gt; i naciskiem na &lt;span class="caps"&gt;AJAX&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://enigo.com/projects/iowa/"&gt;&lt;span class="caps"&gt;IOWA&lt;/span&gt;&lt;/a&gt; &amp;#8211; komponentowy, &lt;/li&gt;
		&lt;li&gt;&lt;a href="https://rubyforge.org/projects/wee/"&gt;Wee&lt;/a&gt; wzorowany na smalltalkowym &lt;a href="http://www.seaside.st/"&gt;Seaside&lt;/a&gt; u&#380;ywaj&#261;cym &lt;a href="http://en.wikipedia.org/wiki/Continuation"&gt;kontynuacji&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://sinatra.rubyforge.org/"&gt;Sinatra&lt;/a&gt; &amp;#8211; mikroframework wzorowany na minimalistycznym, pythonowym &lt;a href="http://webpy.org"&gt;Web.py&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://sergiosantos.info/2007/7/camping-a-ruby-microframework"&gt;Camping&lt;/a&gt; &amp;#8211; kolejny mikroframework w Ruby&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://rubywaves.com/"&gt;Wave&lt;/a&gt; &amp;#8211; wzorowany na Camping, te&#380; u&#380;ywa Rack i Rubiego wsz&#281;dzie gdzie si&#281; da.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/macournoyer/invisible/tree/master"&gt;Invisible&lt;/a&gt; mikroframework u&#380;ywaj&#261;cy Rack napisany w 35 linijkach kodu Rubiego (bardziej ciekawostka)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Mongrel i sp&#243;&#322;ka&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.webrick.org/"&gt;Webrick&lt;/a&gt; &amp;#8211; serwer http dost&#281;pny razem ze standardow&#261; bibliotek&#261; Rubiego&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://dev.robotcoop.com/Libraries/webrick-high-performance/classes/WEBrick/HighPerformanceServer.html"&gt;Highperformance Webrick&lt;/a&gt; &amp;#8211; szybsza wersja Webricka (u&#380;ywaj&#261;ca uniksowych fork&#243;w)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://mongrel.rubyforge.org/"&gt;Mongrel&lt;/a&gt; &amp;#8211; klasyka, napisany cz&#281;&#347;ciowo w C, to od niego zacz&#281;&#322;a si&#281; rewolucja i odej&#347;cie od FastCGI jako metody odpalania Rails&#243;w.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://swiftiply.swiftcore.org/mongrel.html"&gt;Swiftyply i evented_mongrel&lt;/a&gt; asychroniczne, szybsze wersje Mongrela&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://code.macournoyer.com/thin/"&gt;&lt;strong&gt;Thin&lt;/strong&gt;&lt;/a&gt; &amp;#8211; asynchroniczny web server u&#380;ywaj&#261;cy Mongrela i Rack&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://ebb.rubyforge.org/"&gt;&lt;strong&gt;Ebb&lt;/strong&gt;&lt;/a&gt; &amp;#8211; u&#380;ywa Rack, wi&#281;kszo&#347;&#263; kodu jest w C, dlatego jest taki szybki, na razie ma&#322;o dokumentacji, by&#263; mo&#380;e nast&#281;pca Thin&lt;/li&gt;
	&lt;/ul&gt;</description>
      <pubDate>Tue, 04 Mar 2008 22:56:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:bdcbae56-a710-43b1-84a6-77d5471f8cac</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/03/04/frameworki-rubiego-rack-wsgi</link>
      <category>merb</category>
      <category>jruby</category>
      <category>rack</category>
      <category>python</category>
      <category>ruby</category>
      <category>frameworks</category>
      <category>thin</category>
      <category>rails</category>
      <category>ramaze</category>
      <category>mongerl</category>
      <category>ebb</category>
      <category>fuzed</category>
    </item>
    <item>
      <title>Thin, unix sockets, Rails i Merb</title>
      <description>&lt;p&gt;&lt;a href="http://code.macournoyer.com/thin/"&gt;Thin&lt;/a&gt; to szybki serwer &lt;span class="caps"&gt;HTTP&lt;/span&gt; s&#322;u&#380;&#261;cy do uruchamiania webowych framework&#243;w napisanych w j&#281;zyku Ruby. Najbardziej z nich popularny jest oczywi&#347;cie &lt;a href="http://rubyonrails.pl"&gt;Rails&lt;/a&gt;. Cho&#263; istnieje wiele sposob&#243;w uruchomienia Rails&#243;w na serwerze produkcyjnym, u&#380;ycie Thin wydaje si&#281; aktualnie najlepszym rozwi&#261;zaniem z przynajmniej dw&#243;ch powod&#243;w: zajmuje mniej pami&#281;ci i jest szybszy od popularnego &lt;a href="http://mongrel.rubyforge.org/"&gt;Mongrela&lt;/a&gt;. Thin wykorzystuje dwa bardzo szybkie modu&#322;y: &lt;a href="http://www.zedshaw.com/tips/ragel_state_charts.html"&gt;Mongel parser&lt;/a&gt;, &lt;a href="http://rubyeventmachine.com/"&gt;Event Machine&lt;/a&gt; oraz (wzorowan&#261; na pythonowym &lt;a href="http://www.python.org/dev/peps/pep-0333/"&gt;&lt;span class="caps"&gt;WSGI&lt;/span&gt;&lt;/a&gt;) bibliotek&#281; &lt;a href=""http://rack.rubyforge.org/"&gt;Rack&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Od jakiego&#347; czasu Thin udost&#281;pnia uruchamianie klastra proces&#243;w wykorzystuj&#261;cy szybsze od &lt;span class="caps"&gt;TCP&lt;/span&gt;, sockety uniksowe. Zalet&#261; jest nie tylko wi&#281;ksza szybko&#347;&#263; pracy, ale tak&#380;e odpada problem rezerwacji odpowiedniej liczby port&#243;w &lt;span class="caps"&gt;TCP&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Wygenerowanie pliku konfiguracyjnego polega na uruchomieniu w katalogu z projektem Rails (lub Merb) komendy:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;thin config -C config/thin.yml -s4 -e production \
  --socket /tmp/thin_myapp.sock&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Zostanie wygenerowany plik konfiguracyjny o mniej wi&#281;cej takiej tre&#347;ci:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_yaml "&gt;&lt;span class="document"&gt;--- 
pid: tmp/pids/thin.pid&lt;/span&gt;
&lt;span class="key"&gt;socket&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; /tmp/thin_myapp.sock
&lt;span class="key"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; log/thin.log
&lt;span class="key"&gt;max_conns&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 1024
&lt;span class="key"&gt;timeout&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 30
&lt;span class="key"&gt;chdir&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; /home/app/rails/myapp
&lt;span class="key"&gt;environment&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; production
&lt;span class="key"&gt;max_persistent_conns&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 512
&lt;span class="key"&gt;servers&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 4
&lt;span class="key"&gt;daemonize&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; true&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Opcja &lt;code&gt;-s4&lt;/code&gt; oznacza &#380;e chcemy u&#380;y&#263; 4 procesy. (W wypadku Nginksa, trzeba uwa&#380;a&#263; na opcj&#281; &lt;code&gt;max_persistent_conns&lt;/code&gt;, bo Nginx zdaje si&#281; nie ma jeszcze zaimplementowanej obs&#322;ugi persistent connections. Najlepiej j&#261;  wy&#322;&#261;czy&#263;, tzn. przypisa&#263; jej warto&#347;&#263; r&#243;wn&#261; zeru. Apache powinien to obs&#322;ugiwa&#263;. Z persistent connections wszystko powinno dzia&#322;a&#263; troch&#281; szybciej.)&lt;/p&gt;


	&lt;p&gt;Aby to uruchomi&#263;, warto stworzy&#263; plik startowy. Dla Debiana/Ubuntu nale&#380;y stworzy&#263; plik &lt;code&gt;/etc/init.d/thin.rb&lt;/code&gt; (dla wygody napisalem to w Ruby zamiast Bashu):&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;fileutils&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;FileUtils&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;pids&lt;/span&gt;
  &lt;span class="constant"&gt;Dir&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;glob&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;tmp/pids/thin*.pid&lt;/span&gt;&lt;span class="punct"&gt;').&lt;/span&gt;&lt;span class="ident"&gt;map&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;entry&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; 
    &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;open&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;entry&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;read&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;start&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;pids&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;empty?&lt;/span&gt;
    &lt;span class="ident"&gt;rm_f&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;tmp/pids/thin*.pid&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;exists?&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;config/init.rb&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="comment"&gt;# start Merb&lt;/span&gt;
      &lt;span class="ident"&gt;system&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;thin start -r config.ru -C config/thin.yml&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt; &lt;span class="comment"&gt;# start Rails&lt;/span&gt;
      &lt;span class="ident"&gt;system&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;thin start -C config/thin.yml&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;else&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Thin cluster is already working&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;stop&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;pids&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;empty?&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Thin cluster is not working&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;else&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Stopping thin cluster&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="ident"&gt;pids&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;empty?&lt;/span&gt;
    &lt;span class="ident"&gt;pids&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;pid&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;system&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;kill -TERM &lt;span class="expr"&gt;#{pid}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="ident"&gt;rm_f&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;tmp/pids/thin*.pid&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;restart&lt;/span&gt;
  &lt;span class="ident"&gt;stop&lt;/span&gt;
  &lt;span class="ident"&gt;sleep&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
  &lt;span class="ident"&gt;start&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;status&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;pids&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;empty?&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Thin cluster is not working&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;else&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Thin cluster is working (pids: &lt;span class="expr"&gt;#{pids.join ', '}&lt;/span&gt;)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;__FILE__&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="global"&gt;$0&lt;/span&gt;
  &lt;span class="ident"&gt;opts&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;%w(&lt;/span&gt;&lt;span class="string"&gt;start stop restart status&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;opts&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;exists?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
    &lt;span class="constant"&gt;Dir&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;chdir&lt;/span&gt; &lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
    &lt;span class="ident"&gt;eval&lt;/span&gt; &lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="keyword"&gt;else&lt;/span&gt;
    &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Syntax: ruby {&lt;span class="expr"&gt;#{File.basename($0)}&lt;/span&gt; &amp;lt;&lt;span class="expr"&gt;#{opts.join '|'}&lt;/span&gt;}&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt;  &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; /path/to/rails_or_merb/project&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Nale&#380;y doda&#263; uprawnienia (&lt;code&gt;sudo chmod a+x thin.rb&lt;/code&gt;) i ustawi&#263; aby domy&#347;lnie, podczas uruchomienia ca&#322;ego serwera by&#322; uruchamiany nast&#281;puj&#261;cy skrypt (&lt;code&gt;thin_myapp.rb&lt;/code&gt;) dla konkretnego projektu Rails lub Merb (komenda &lt;code&gt;sudo update-rc.d -f thin_myapp.rb defaults&lt;/code&gt;).&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;span class="ident"&gt;path&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/path/to/rails-or-merb/project&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="ident"&gt;opts&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;%w(&lt;/span&gt;&lt;span class="string"&gt;start stop restart status&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;opts&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt; &lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="ident"&gt;system&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/etc/init.d/thin.rb &lt;span class="expr"&gt;#{ARGV[0]}&lt;/span&gt; &lt;span class="expr"&gt;#{path}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;else&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Syntax: &lt;span class="expr"&gt;#{File.basename(__FILE__)}&lt;/span&gt; {&lt;span class="expr"&gt;#{opts.join '|'}&lt;/span&gt;}&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W wypadku &lt;a href="http://www.merbivore.com/"&gt;Merba&lt;/a&gt; trzeba pami&#281;ta&#263; aby stworzy&#263; dodatkowy plik konfiguracyjny &lt;code&gt;config.ru&lt;/code&gt; (oczywi&#347;cie dotyczy to Merba 0.9 lub nowszego):&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# config.ru&lt;/span&gt;
&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;BootLoader&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;run&lt;/span&gt;
&lt;span class="ident"&gt;run&lt;/span&gt; &lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Rack&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Application&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Wy&#380;ej podany plik startowy rozpoznaje czy projekt to Rails czy Merb na podstawie odnalezienia pliku &lt;code&gt;config/init.rb&lt;/code&gt;. Ale jak kto&#347; chce odpala&#263; to r&#281;cznie to Merba korzystaj&#261;cego z Thina i jego plikiu konfiguracyjnego (&lt;code&gt;config/thin.yml&lt;/code&gt;) odpala si&#281; w taki spos&#243;b:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;thin start -r config.ru -C config/thin.yml&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Teraz wystarczy tylko ustawi&#263; load balancing do tak uruchomionego serwera. Dla serwera &lt;a href="http://nginx.net"&gt;Nginx&lt;/a&gt; b&#281;dzie to&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_nginx "&gt;upstream thin_myapp {
  server unix:/tmp/thin_myapp.0.sock;
  server unix:/tmp/thin_myapp.1.sock;
  server unix:/tmp/thin_myapp.2.sock;
  server unix:/tmp/thin_myapp.3.sock;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I w definicji serwera wirtualnego:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_nginx "&gt;if (!-f $request_filename) {
  proxy_pass http://thin_myapp;
  break;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Zobacz te&#380;:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://macournoyer.wordpress.com/2008/01/26/get-intimate-with-your-load-balancer-tonight/"&gt;Get intimate with your load balancer tonight!&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://macournoyer.wordpress.com/2008/02/24/staying-alive-with-thin/"&gt;Staying Alive with Thin!&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;em&gt;Update 2008-03-04:&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Poprawi&#322;em skrypt startowy tak aby by&#322; bardziej uniwersalny w wypadku u&#380;ywania wielu projekt&#243;w Rails (lub Merb). Doda&#322;em te&#380; informacje o mo&#380;liwym problemie ze zmienn&#261; &lt;code&gt;max_persistent_conns&lt;/code&gt; w wypadku Nginksa.&lt;/p&gt;</description>
      <pubDate>Mon, 03 Mar 2008 03:36:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:fae56603-7950-4af5-8324-c4df90572cd0</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/03/03/thin-sockets-rails-merb</link>
      <category>merb</category>
      <category>thin</category>
      <category>rails</category>
      <category>unix</category>
      <category>nginx</category>
    </item>
    <item>
      <title>Merb 0.9 continious gem rebuilding</title>
      <description>&lt;p&gt;Niedawno opublikowane na RubyForge gemy Merb o wersji 0.9 wcale nie oznaczaj&#261; &#380;e jest to wersje produkcyjna. Podobnie jak w wypadku Rubiego 1.9, tw&#243;rcy Merba 0.9 okre&#347;laj&#261; t&#261; wersj&#281; jako &lt;em&gt;developersk&#261;&lt;/em&gt;. Jej celem jest wyczyszczenie b&#322;&#281;d&#243;w przed maj&#261;ca nadej&#347;&#263; wersj&#261; 1.0. Moim zdaniem nie ma sensu korzysta&#263; z gem&#243;w 0.9, lepiej od razu wskoczy&#263; na wersj&#281;&#160;edge.&lt;/p&gt;


	&lt;h2&gt;Frozen Merb&lt;/h2&gt;


	&lt;p&gt;Kod Merb&amp;#8217;a 0.9 zosta&#322; troch&#281; podzielony na kilka mniejszych gem&#243;w. Celem takiego podej&#347;cia jest wi&#281;ksza elastyczno&#347;&#263;. Mniejsza o to. Nowy gem &lt;code&gt;gem-gen&lt;/code&gt; udost&#281;pnia skrypt zamra&#380;aj&#261;cy framdework. Nale&#380;y w katalogu z projektem stworzy&#263; katalog &lt;code&gt;framework&lt;/code&gt; i tam zainstalowa&#263; najnowszy kod rozwojowy. Trzeba mie&#263; oczywi&#347;cie zainstalowany system wersjonowania kodu &amp;#8211; Git (&lt;code&gt;port install git-core&lt;/code&gt; dla &lt;span class="caps"&gt;OSX&lt;/span&gt;, lub &lt;code&gt;sudo apt-get install git-core&lt;/code&gt; dla Linuksa).&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;mkdir framework
cd framework
git clone git://github.com/wycats/merb-core.git
git clone git://github.com/wycats/merb-more.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Wszystkie generatory s&#261; w Merbie realizowane przez skrypt &lt;code&gt;merb-gen&lt;/code&gt; (oparty na gemie o tej samej nazwie). Jedn&#261; z opcji merb-gen&amp;#8217;a jest mo&#380;liwo&#347;&#263; stworzenia specjalnego skryptu kt&#243;ry b&#281;dzie odpala&#322;&#160;gemy Merba z naszego katalogu &lt;code&gt;framework&lt;/code&gt; zamiast z systemu. Skrypt mo&#380;na stworzy&#263; za pomoc&#261; komendy.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;merb-gen freezer frozen_merb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Od tej chwili mo&#380;na odpala&#263; projekt za pomoc&#261; komendy &lt;code&gt;script/frozen-merb&lt;/code&gt;. Dla wygody, podaj&#281; kod tasku rake&amp;#8217;a aktualizuj&#261;cego biblioteki w katalogu &lt;code&gt;framework&lt;/code&gt;. Kod jest prosty, przechodzi do podkatalogu i odpala komend&#281; &lt;code&gt;git pull&lt;/code&gt;.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;desc&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Update all gits from frozen framework&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;namespace&lt;/span&gt; &lt;span class="symbol"&gt;:framework&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;task&lt;/span&gt; &lt;span class="symbol"&gt;:update&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;    
    &lt;span class="ident"&gt;framework_path&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;root&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;framework&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;directory?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;framework_path&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;core&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;more&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;plugins&lt;/span&gt;&lt;span class="punct"&gt;'].&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
        &lt;span class="ident"&gt;path&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;framework_path&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;merb-&lt;span class="expr"&gt;#{x}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
        &lt;span class="ident"&gt;sh&lt;/span&gt; &lt;span class="punct"&gt;%{&lt;/span&gt;&lt;span class="string"&gt;cd &lt;span class="expr"&gt;#{path}&lt;/span&gt;; git pull&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Niestety, nie jest to rozwi&#261;zanie idealne, bo sam skrypt &lt;code&gt;frozen-merb&lt;/code&gt; zak&#322;ada &#380;e mamy w systemie zainstalowany gem &lt;code&gt;merb-core&lt;/code&gt;. Podobnie nie dzia&#322;aj&#261; zadania Rake&amp;#8217;a je&#347;liw  systemie nie ma &#380;adnych gem&#243;w Merba. Troch&#281; to niekonsekwentne, bo cz&#281;&#347;&#263; kodu korzysta z edge a cz&#281;&#347;&#263; ze starszych gem&#243;w w systemie. Problem ten rozwi&#261;zuje zupe&#322;nie inny pomys&#322;.&lt;/p&gt;


	&lt;h2&gt;Continious gem rebuilding&lt;/h2&gt;


	&lt;p&gt;W tym wypadku po prostu ka&#380;da aktualizja kodu rozwojowego automatycznie przebudowuje gemy w systemie. Poni&#380;szy kod zadzia&#322;a nawet jak w systemie nie mamy zainstalowanego ani jednego gemu Merba (z tego te&#380; powodu nie umieszczam go jako zadanie Rake&amp;#8217;a) Skrypt nale&#380;y skopiowa&#263; do podkatalogu &lt;code&gt;framework&lt;/code&gt; (cho&#263; mo&#380;na go lekko zmodyfikowa&#263; aby dzia&#322;a&#322; z dowolnego katalogu). Ca&#322;y kod sprowadza si&#281; do odpalenia od czasu poni&#380;szego skryptu.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;span class="punct"&gt;%w(&lt;/span&gt;&lt;span class="string"&gt;merb-core merb-more merb-plugins&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;entry&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Updating git for &lt;span class="expr"&gt;#{entry}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;system&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;cd &lt;span class="expr"&gt;#{entry}&lt;/span&gt;; git pull&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="punct"&gt;%w(&lt;/span&gt;&lt;span class="string"&gt;merb-plugins/merb_* merb-more/merb-* merb-more merb-core&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;entry&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="constant"&gt;Dir&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;glob&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;entry&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;dir&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; 
    &lt;span class="ident"&gt;system&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;cd &lt;span class="expr"&gt;#{dir}&lt;/span&gt;; rake repackage&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;system&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;sudo gem uninstall -a -i -x &lt;span class="expr"&gt;#{File.basename(dir)}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;span class="keyword"&gt;rescue&lt;/span&gt; &lt;span class="constant"&gt;Gem&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;InstallError&lt;/span&gt; 
    &lt;span class="ident"&gt;system&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;sudo gem install --no-rdoc --no-ri -f -l &lt;span class="expr"&gt;#{dir}&lt;/span&gt;/pkg/*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W tej metodzie &lt;strong&gt;nie&lt;/strong&gt; musimy odpala&#263; &lt;code&gt;script/frozen-merb&lt;/code&gt;, wystarczy zwyk&#322;a komenda &lt;code&gt;merb&lt;/code&gt;. Powy&#380;szy skrypt doda&#322;em do repozytorium Merba jako &lt;a href="http://merb.lighthouseapp.com/projects/7433-merb-core/tickets/143-enhancement-continious-edge-gem-rebuilder"&gt;proponowane ulepszenie&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Najnowsza dokumentacja RDoc do merb-core umieszczona jest na &lt;a href="http://blog.zabiello.com/merb-core/"&gt;http://blog.zabiello.com/merb-core/&lt;/a&gt; (jest od&#347;wie&#380;ana co godzin&#281;).&lt;/p&gt;</description>
      <pubDate>Wed, 20 Feb 2008 16:10:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:5446736c-6529-4faa-98dc-cd81958d8a0d</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/02/20/merb-0-9-continious-gem-rebuilding</link>
      <category>merb</category>
    </item>
    <item>
      <title>Merb 0.5</title>
      <description>&lt;p&gt;Konkurencja Rails&#243;w przy&#347;piesza. Ezra Zygmuntowicz i jego team wypu&#347;cili &lt;a href="http://brainspl.at/articles/2008/01/10/merb-0-5-0-is-out"&gt;now&#261; wersj&#281;&lt;/a&gt; Merb&amp;#8217;a 0.5. Nowa wersja zawiera wiele usprawnie&#324;, w repozytorium zosta&#322;a oznaczona jako &amp;#8220;The big cleanup&amp;#8221;. M.in. usprawniono  wsp&#243;&#322;prac&#281; z &lt;a href="http://haml.hamptoncatlin.com/"&gt;Hamlem&lt;/a&gt; za pomoc&#261; prekompilacji i szybszego includowania hamlowych partiali. Wbudowano wsparcie dla &lt;a href="http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html"&gt;Sass&lt;/a&gt; dodaj&#261; podkatalog &lt;code&gt;sass&lt;/code&gt; w katalogu &lt;code&gt;public&lt;/code&gt;. Przyby&#322;o te&#380; generator&#243;w kodu, &lt;a href="http://pastie.caboo.se/137630"&gt;pozbyto si&#281;&lt;/a&gt; brzydkich sta&#322;ych, itp., itd. Pojawi&#322;y si&#281; te&#380; nowe wersje gem&#243;w  &lt;code&gt;merb_datamapper&lt;/code&gt;, &lt;code&gt;merb_sequel&lt;/code&gt;, &lt;code&gt;merb_activerecord&lt;/code&gt; i &lt;code&gt;merb_helpers&lt;/code&gt;. Nowa wersja Merba zosta&#322;a nazwana &amp;#8220;Thanks Zed&amp;#8221; (w podzi&#281;kowaniu dla &lt;a href="http://www.zedshaw.com/"&gt;Zeda Shaw&lt;/a&gt;, tw&#243;rcy &lt;a href="http://mongrel.rubyforge.org/"&gt;Mongrela&lt;/a&gt;)&lt;/p&gt;</description>
      <pubDate>Thu, 10 Jan 2008 11:53:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:44f60c16-59c3-4d7a-a89d-d96d4eceade1</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/01/10/merb-0-5</link>
      <category>merb</category>
      <category>ruby</category>
      <category>haml</category>
    </item>
    <item>
      <title>W&#347;ciek&#322;y Zed i dyskusja wok&#243;&#322; Rubiego i Rails&#243;w</title>
      <description>&lt;p&gt;Ostatnio jest troch&#281; szumie w bran&#380;y po bezpardonowym (i niewybrednym) &lt;a href="http://www.zedshaw.com/rants/rails_is_a_ghetto.html"&gt;ataku Zeda Shaw&lt;/a&gt; uderzaj&#261;cym w kilka znanych postaci z kr&#281;g&#243;w Rubiego i Rails. Pewnie nikt by na to nie zwr&#243;ci&#322; uwagi gdyby nie to, &#380;e Zed jest autorem znanego projektu &lt;a href="http://mongrel.rubyforge.org/"&gt;Mongrel&lt;/a&gt;. Cho&#263; wpis si&#281; &#378;le czyta (bo jest rozwlek&#322;y i niepotrzebnie przeplatany ci&#261;g&#322;ymi przekle&#324;stwami autora) to zwr&#243;ci&#322; uwag&#281; na kilka istotnych problem&#243;w.&lt;/p&gt;


	&lt;p&gt;Autor zwraca uwag&#281;, &#380;e core team Rails&#243;w dosy&#263; opornie i wolno reaguje na podsy&#322;ane uwagi i poprawki. Fakt, jedn&#261; z poprawek jak&#261; kiedy&#347; podes&#322;a&#322;em odno&#347;nie &#378;le dzia&#322;aj&#261;cej funkcji render_to_string uwzgl&#281;dniono po.. o&#347;miu miesi&#261;cach. Zed si&#281; wkurzy&#322;, &#380;e ignorowano jego uwagi a potem i tak wychodzi&#322;o na jego. Tak z po&#322;owa core teamu to wg niego banda idiot&#243;w z wyp&#322;ukanymi przez &lt;span class="caps"&gt;PHP&lt;/span&gt;  m&#243;zgami. Ze swej strony bym m&#243;g&#322; do tej listy niekompetencji owej &amp;#8220;bandy&amp;#8221; te&#380; co&#347; do&#322;o&#380;y&#263;, ale to nie jest najwa&#380;niejsze. Jest reszta, kt&#243;ra dobrze robi swoj&#261; robot&#281;.  Ale mo&#380;e taka krytyka podzia&#322;a jak kube&#322; zimnej wody i w ko&#324;cu ca&#322;y core team zacznie skupia&#263; si&#281; na jako&#347;ci i optymalizacji ju&#380; istniej&#261;cego kodu. Bo jak nie, to programi&#347;ci Rails zaczn&#261; sukcesywnie przesuwa&#263; si&#281; do konkurencyjnego projektu &lt;a href="http://merbivore.com/"&gt;Merb&lt;/a&gt;. Ezra Zygmuntowicz udowodni&#322;, &#380;e mo&#380;na napisa&#263; &amp;#8220;lepsze Railsy&amp;#8221; (szybsze,  wielow&#261;tkowe i bardziej przejrzyste). Podoba mi si&#281; in&#380;ynieryjne podej&#347;cie Ezry Zygmuntowicza. Jego Merb jest bardzo &#322;adny, przejrzysty i szybki. Co ciekawe, Ezra zatrudni&#322; kilku developer&#243;w &lt;a href="http://rubini.us/"&gt;Rubiniusa&lt;/a&gt;. Zapowiada si&#281; &#380;e Railsy w ko&#324;cu spotka&#322;y bardzo trudn&#261; konkurencj&#281; (i bardzo dobrze). Sytuacj&#281; Rals&#243;w pog&#322;&#281;bia to, &#380;e nowe &lt;span class="caps"&gt;ORM&lt;/span&gt;&amp;#8217;y takie jak &lt;a href="http://datamapper.org/why.html"&gt;DataMapper&lt;/a&gt; i &lt;a href="http://code.google.com/p/ruby-sequel/"&gt;Sequel&lt;/a&gt; r&#243;wnie&#380; stanowi&#261; zagro&#380;enie dla dominacji &lt;a href="http://ar.rubyonrails.com/"&gt;Active Record&lt;/a&gt; nawet w kontek&#347;cie Rails&#243;w.&lt;/p&gt;


	&lt;h3&gt;PickAxe i inne ksi&#261;&#380;ki&lt;/h3&gt;


	&lt;p&gt;Zed przeprowadzi&#322; bardzo ciekaw&#261; krytyk&#281; chwalonej &lt;a href="http://helion.pl/ksiazki/prruby.htm"&gt;PickAxe&lt;/a&gt;. Ostro rozjecha&#322; autora za u&#380;ywanie g&#322;upich przyk&#322;ad&#243;w, niezgodnego z konwencjami Rubiego nazewnictwem zmiennych, i co najwa&#380;niejsze, omini&#281;cie szerokim &#322;ukiem najwa&#380;niejszej i najbardziej atrakcyjnej cechy Rubiego &amp;#8211; &#322;atwo&#347;ci metaprogramowania. PickAxe, zdaniem Zeda, odwo&#322;uje si&#281; do starych praktyk projektowania obiektowego z roku 2001. Zed idzie nawet dalej, uwa&#380;a &#380;e ta ksi&#261;&#380;ka promuje z&#322;e nawyki programistyczne i zach&#281;ca do pisania z&#322;ego kodu. Twierdzi nawet, &#380;e ta ksi&#261;&#380;ka zamiast pom&#243;c, zaszkodzi&#322;a Rubiemu aby wcze&#347;niej wyp&#322;yn&#261;&#322; na szerok&#261; scen&#281;.&lt;/p&gt;


	&lt;p&gt;Faktycznie, w latach 2001-2004 o Ruby praktycznie nikt nie s&#322;ysza&#322;. Jakie&#347; nieliczne wyj&#261;tki uczy&#322;y si&#281; Rubiego na &lt;a href="http://www.ruby-doc.org/docs/ProgrammingRuby/"&gt;ksi&#261;&#380;ce Dave&amp;#8217;a Thomasa&lt;/a&gt; ale j&#281;zyk jako taki by&#322; czym&#347; bardzo malo znanym. Sytuacj&#281; zmieni&#322;o dopiero pojawienie &lt;a href="http://rubyonrails.org"&gt;Ruby on Rails&lt;/a&gt; w 2005 roku, ktore spowodowa&#322;y &lt;strong&gt;znacz&#261;cy wzrost&lt;/strong&gt; popularno&#347;ci Rubiego (ja sam te&#380; zainteresowa&#322;em si&#281; te&#380; Railsami, a dopiero p&#243;&#378;niej Rubim). &lt;strong&gt;Dopiero Railsy pokaza&#322;y pi&#281;kno i moc metaprogramowania w Ruby&lt;/strong&gt;, co&#347; co zachwyci&#322;o rzesze ludzi, co&#347; czego nie maj&#261; inne j&#281;zyki. I nie wiem jak by si&#281; wysilano, nie da si&#281; uzyska&#263; tak pi&#281;knego i eleganckiego metaproramowania w &lt;span class="caps"&gt;PHP&lt;/span&gt;, Javie, czy nawet Pythonie. Zed bezpardonowo stwierdzi&#322;, &#380;e PickAxe tylko zaszkodzi&#322; Rubiemu zamiast mu pom&#243;c.&lt;/p&gt;


	&lt;p&gt;Wpierw mnie zaskoczy&#322;a ta opinia, ale p&#243;&#378;niej, jak si&#281; zastanowi&#322;em, to musz&#281; przyzna&#263; &#380;e du&#380;o w tym racji. Nigdy do mnie nie przemawia&#322;y u&#380;yte w ksi&#261;&#380;ce przyk&#322;ady. Ceni&#322;em j&#261; g&#322;&#243;wnie za to, &#380;e w og&#243;le jest cokolwiek na temat Rubiego, i &#380;e opisano bibliotek&#281; standardow&#261; Rubiego. Jestem ciekaw, co Zed by powiedzia&#322; na ksi&#261;&#380;k&#281; Hala Fultona &amp;#8220;The Ruby Way&amp;#8221;. Jej drugie wydanie w&#322;a&#347;nie &lt;a href="http://helion.pl/ksiazki/swruby.htm"&gt;zosta&#322;o wydane po polsku&lt;/a&gt;. Szkoda tylko, &#380;e ma w polskim wydaniu myl&#261;cy tytu&#322; sugeruj&#261;cy, &#380;e to tylko jaki&#347; zestaw 400 przyk&#322;ad&#243;w. Ksi&#261;&#380;k&#281; si&#281; dosy&#263; dobrze czyta. Lepiej ni&#380; PickAxe. T&#261; pierwsz&#261; troch&#281; traktuj&#281; jak podr&#281;cznik do bibliotek Rubiego.&lt;/p&gt;


	&lt;p&gt;Co ciekawe, dosta&#322;o si&#281; te&#380; troch&#281; ksi&#261;&#380;ce &lt;a href="http://helion.pl/ksiazki/agilep.htm"&gt;Agile&lt;/a&gt; :) Ale generalnie du&#380;o nie ma co si&#281; przyczepi&#263;. Ksi&#261;&#380;ka jest raczej dobrze napisana, szkoda tylko, &#380;e opisuje starsze Rails 1.2 a nie 2.0. No c&#243;&#380;, nie wiadomo czy wyjdzie trzecie wydanie, bo &lt;a href="http://www.loudthinking.com/about.html"&gt;&lt;span class="caps"&gt;DHH&lt;/span&gt;&lt;/a&gt; jako&#347; si&#281; do niego nie pali.&lt;/p&gt;


	&lt;p&gt;Z ciekawo&#347;ci sprawdzi&#322;em inn&#261; ksi&#261;&#380;k&#281;, polecan&#261; przez Zeda, &lt;a href="http://www.amazon.com/Rails-Way-Addison-Wesley-Professional-Ruby/dp/0321445619/"&gt;The Rails Way&lt;/a&gt;. Faktycznie wygl&#261;da na dobrze napisan&#261; i uwzgl&#281;dnia nowsze cechy Rails&#243;w. Jest dost&#281;pna online (cho&#263; nie za darmo) przez &lt;a href="http://safari.oreilly.com/"&gt;O&amp;#8217;Reilly Safari Books Online&lt;/a&gt; (tak w og&#243;le to &#347;wietny serwis, kt&#243;ry warto sobie zaprenumerowa&#263;).&lt;/p&gt;


	&lt;h3&gt;Rubinius, JRuby i Jubinius&lt;/h3&gt;


	&lt;p&gt;Zed si&#281; wkurzy&#322;, nabluzga&#322;, ale zwr&#243;ci&#322; uwag&#281; na kilka wa&#380;nych kwestii. Tak&#380;e odno&#347;nie samego Rubiego to pochwa&#322;a dosta&#322;a si&#281; &lt;a href="http://jruby.codehaus.org/"&gt;JRuby&lt;/a&gt; i &lt;a href="http://rubini.us/"&gt;Rubiniusowi&lt;/a&gt;. Szczeg&#243;lnie ten drugi mo&#380;e wkr&#243;tce kompletnie zagrozi&#263; dominacji &lt;span class="caps"&gt;MRI&lt;/span&gt; jaki jest u&#380;ywany w dzisiejszej, opartej na C, implemementacji Rubiego. Je&#347;li szybko nie powstanie kompletnie uko&#324;czony &lt;a href="http://www.atdot.net/yarv/"&gt;&lt;span class="caps"&gt;YARV&lt;/span&gt;&lt;/a&gt; (w&#322;&#261;czony do Ruby 1.9), to Rubinius zwyci&#281;&#380;y. Temat Rubiniusa jest on tematem naszych dyskusji na kanale &lt;span class="caps"&gt;IRC&lt;/span&gt; &lt;a href="irc://irc.eu.freenode.net/rubyonrails.pl"&gt;#rubyonrails.pl&lt;/a&gt;. Podej&#347;cie jest tu troch&#281; podobne do pythonowego &lt;a href="http://codespeak.net/pypy/dist/pypy/doc/news.html"&gt;PyPy&lt;/a&gt;, cho&#263; Rubinius nawi&#261;zuje bardziej do 30 lat do&#347;wiadcze&#324; &lt;a href="http://www.smalltalk.org/main/"&gt;Smalltalka&lt;/a&gt;. Celem jest stworzenie najszybszej wirtualnej maszyny Rubiego oraz &#322;atwego i szybkiego rozwoju dla samego Rubiego. Dzi&#281;ki temu, &#380;e mamy tu do czynienia z Ruby kt&#243;rego implementacja napisana jest w Ruby, znacznie &#322;atwiej jest rozwija&#263; j&#281;zyk.&lt;/p&gt;


	&lt;p&gt;Co ciekawe, autorzy JRuby zastanawiaj&#261; si&#281; czy nie zrobi&#263; podobnie. I ju&#380; s&#261; dyskusj&#281; o tym aby stworzy&#263; analogicznie &lt;a href="http://ola-bini.blogspot.com/2007/09/rubinius-is-important.html"&gt;Jubiniusa&lt;/a&gt;. Tak jak Rubinius w &#322;atwy spos&#243;b wci&#261;ga biblioteki napisane w C, Jubinius wci&#261;ga&#322;by te napisane w Javie. Jubinius mia&#322;by dodatkowo o tyle wygodniejsz&#261; sytuacj&#281;, &#380;e implementacja ca&#322;ej biblioteki standardowej Rubiego jest ju&#380; przepisana do Rubiego. Jubinius m&#243;g&#322;by z marszu wykorzysta&#263; ten kod.&lt;/p&gt;</description>
      <pubDate>Sun, 06 Jan 2008 23:49:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:1c2f3888-12a8-42dd-b190-ddd345a03248</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2008/01/06/zed-ruby-rails</link>
      <category>mongrel</category>
      <category>ruby</category>
      <category>rubinius</category>
      <category>merb</category>
      <category>rails</category>
      <category>datamapper</category>
      <category>sequel</category>
      <category>activerecord</category>
      <category>jruby</category>
      <category>jubinius</category>
    </item>
  </channel>
</rss>
