<?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: Category Ruby</title>
    <link>http://blog.zabiello.com/articles/category/ruby</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>moje notatki, linki, komentarze</description>
    <item>
      <title>Ruby 1.9 (YARV) vs. Python, Lua &amp;amp; PHP</title>
      <description>&lt;p&gt;Korzystaj&#261;c z tego, &#380;e &lt;a href="http://redhanded.hobix.com/cult/yarvIsRubyItIsItReallyIs.html"&gt;niedawno do repozytorium Rubiego zosta&#322; dodany &lt;span class="caps"&gt;YARV&lt;/span&gt;&lt;/a&gt; (wirtualna maszyna Rubiego)  pokusi&#322;em si&#281; o ma&#322;e por&#243;wnanie wydajno&#347;ci. Jako test u&#380;y&#322;em prostego programu jaki &lt;a href="http://groups.google.com/group/pl.comp.lang.python/browse_thread/thread/61095f8a08ca5f9e/1646948032dc08c0?lnk=st&amp;#38;q=&amp;#38;rnum=2&amp;#38;hl=pl#1646948032dc08c0"&gt;pojawi&#322; si&#281; na li&#347;cie pl.comp.lang.pyhon&lt;/a&gt; (musia&#322;em tylko troch&#281; zwi&#281;kszy&#263; p&#281;tle do 10 milion&#243;w iteracji, aby by&#322;y widoczne jakie&#347; wyniki) U&#380;yty sprz&#281;t: Athlon64 3700+, 64bit Ubuntu 6.0.6.&lt;/p&gt;


	&lt;p&gt;Sprawdzi&#322;em te&#380; z ciekawo&#347;ci &lt;span class="caps"&gt;PHP 5&lt;/span&gt;.2 na tym samym sprz&#281;cie. Dla tak prostego testu powinien m&#243;c da&#263; z siebie wszystko. Jest jednak wolniejszy od Rubiego 1.9.&lt;/p&gt;


	&lt;p&gt;Kod dla Pythona:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;
&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;
&lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;xrange&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;10000000&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt;
&lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;
&lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

Kod dla Lua:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;os&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;clock&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
&lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
&lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;i&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="number"&gt;10000000&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;+&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="ident"&gt;print&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="ident"&gt;print&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;os&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;clock&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Kod dla Rubiego:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;now&lt;/span&gt;
&lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
&lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;..&lt;/span&gt;&lt;span class="number"&gt;10_000_000&lt;/span&gt;
  &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;+&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="constant"&gt;Time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;now&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Kod dla &lt;span class="caps"&gt;PHP&lt;/span&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_php "&gt;&amp;lt;?php
function microtime_float() {
 $time = microtime();
 return (double)substr($time, 11) + (double)substr($time, 0, 8);
}
$t =  microtime_float();
$a = 0;
for ($i = 0; $i &amp;lt; 10000000; $i++) {
  $a += $i;
}
print &amp;quot;$a\n&amp;quot;;
print  microtime_float()- $t;
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Wyniki:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Lua: 1.14 s&lt;/li&gt;
		&lt;li&gt;Ruby 1.9: &lt;strong&gt;1.49 s&lt;/strong&gt;&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;PHP 5&lt;/span&gt;.2: 1.74 s&lt;/li&gt;
		&lt;li&gt;Python 2.5: 2.64 s&lt;/li&gt;
		&lt;li&gt;Python 2.4.3: 2.72 s&lt;/li&gt;
		&lt;li&gt;Ruby 1.8.5: 3.83 s.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;h2&gt;Drugie podej&#347;cie&lt;/h2&gt;


	&lt;p&gt;Tym razem wynik u&#347;redniam dla 10 pr&#243;b. Zwi&#281;kszy&#322;em ilo&#347;&#263; iteracji do &lt;strong&gt;20 mln&lt;/strong&gt;. No i&amp;#8230; Ruby 1.9 pobi&#322; wszystko. Zar&#243;wno Pythona jak i Lua! (PHP 5.2 po 30 sek. zg&#322;osi&#322; timeout. Musia&#322;em wi&#281;c u&#347;redni&#263; po 5 wynikach.)&lt;/p&gt;


	&lt;h3&gt;&lt;span class="caps"&gt;PYTHON&lt;/span&gt;&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;bench&lt;/span&gt;&lt;span class="punct"&gt;():&lt;/span&gt;
    &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;t&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;time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;xrange&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;20000000&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
        &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;+=&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;()-&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;
&lt;span class="ident"&gt;result&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
&lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;range&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;10&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
  &lt;span class="ident"&gt;result&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;bench&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
&lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="ident"&gt;result&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="number"&gt;10.0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;&lt;span class="caps"&gt;RUBY&lt;/span&gt;&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;bench&lt;/span&gt;
  &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;t&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="constant"&gt;Time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;now&lt;/span&gt;
  &lt;span class="number"&gt;20_000_000&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="constant"&gt;Time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;now&lt;/span&gt; &lt;span class="punct"&gt;-&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="ident"&gt;result&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
&lt;span class="number"&gt;10&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;result&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;bench&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;result&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="number"&gt;10&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;&lt;span class="caps"&gt;LUA&lt;/span&gt;&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_lua "&gt;function bench()
  a = 0
  t = os.time()
  for i = 1, 20000000 do
    a = a + i
  end
  return os.time() - t
end
result = 0
for x = 1,10 do
  result = result + bench()
end
print(result/10)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt;&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_php "&gt;&amp;lt;?php
function bench() {
  $a = 0;
  $t =  time();
  for ($i = 0; $i &amp;lt; 20000000; $i++) $a += $i;
  return time() - $t;
}
$result = 0;
for ($x = 1; $x &amp;lt;= 5; $x++) $result += bench();
print $result / 5.0;
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Wyniki&lt;/h3&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;strong&gt;Ruby 1.9:       2.0953268 s.&lt;/strong&gt;&lt;/li&gt;
		&lt;li&gt;Lua 5.1:        2.4 s.&lt;/li&gt;
		&lt;li&gt;Python 2.5:     2.49481592178 s.&lt;/li&gt;
		&lt;li&gt;Python 2.4.3:   2.71687791348 s.&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;PHP 5&lt;/span&gt;.2:        4.2 s.&lt;/li&gt;
		&lt;li&gt;Ruby 1.8.5:     9.0153751 s.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Jestem ciekaw kiedy wyjdzie &lt;a href="http://i.loveruby.net/d/20060220.html#p10"&gt;Rails dostosowany do Ruby 1.9&lt;/a&gt;. Zapowiada si&#281; bardzo obiecuj&#261;co!&lt;/p&gt;</description>
      <pubDate>Mon, 01 Jan 2007 19:36:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:195b9e84-80ff-47b9-a2ae-38070f3da6f0</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2007/01/01/ruby19-yarv</link>
      <category>PHP</category>
      <category>Python</category>
      <category>Ruby</category>
      <category>lua</category>
      <category>python</category>
      <category>ruby</category>
      <category>php</category>
      <category>yarv</category>
      <category>benchmark</category>
    </item>
    <item>
      <title>Skype3 i polski czat dla Rails&#243;w, Django i Pylonsa</title>
      <description>&lt;p&gt;Nowy Skype 3 wprowadza ma&#322;&#261; rewolucj&#281; w stos. do poprzedniej wersji. Mo&#380;na nie tylko rozmawia&#263;, ale pogra&#263; w szachy, k&#243;&#322;ko i krzy&#380;yk i inne gry (s&#261; b. &#322;adnie zrobione we Flashu 9). Mo&#380;na nagrywa&#263; rozmowy na dysk. Mo&#380;na tworzy&#263; publiczne czaty. I w&#322;a&#347;nie w tej sprawie pisz&#281; ten tekst bo 
stworzy&#322;em &lt;a href="http://www.skype.com/go/joinpublicchat?chat&amp;#38;skypename=hipertracker&amp;#38;topic=Rails%2C+Django%2C+Pylons+%28Polish%29&amp;#38;blob=qL-BIeEXX7A-qDj26JrmQcoze6L4kn_YE4016SUPrFY2DUmNoHxxVoeROiE4d1UZFQ4UJUo8-KPFDhFLqFhSVeo"&gt;polski czat dla mi&#322;o&#347;nik&#243;w framework&#243;w Ruby on Rails, Django i Pylons&lt;/a&gt;.
Wygodniej jest czasem skonsultowa&#263; co&#347; w czasie rzeczywistym ni&#380; na grupie czy &lt;a href="http://forum.rubyonrails.pl"&gt;forum dyskusyjnym&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Fri, 15 Dec 2006 00:48:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:6232652d-1ffd-4b4e-bcce-a630cc5bc711</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/12/15/skype3-i-polski-czat-dla-rails%C3%B3w-django-i-pylonsa</link>
      <category>Ruby on Rails</category>
      <category>Pylons</category>
      <category>Python</category>
      <category>Django (en)</category>
      <category>Ruby</category>
      <category>Django</category>
      <category>rails</category>
      <category>django</category>
      <category>pylons</category>
    </item>
    <item>
      <title>PickAxe2 po polsku</title>
      <description>&lt;p style="float:right"&gt;&lt;img src="http://helion.pl/okladki/181x236/prruby.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;Mimo &#380;e o j&#281;zyku Ruby m&#243;wi si&#281; szerzej raczej od niedawna, ilo&#347;&#263; &lt;a href="http://www.ruby-doc.org/bookstore"&gt;ksi&#261;&#380;ek&lt;/a&gt;  i dokumentacji dost&#281;pnej do Rubiego zd&#261;&#380;y&#322;y ju&#380; pobi&#263; to, co zosta&#322;o napisane dla j&#281;zyka Python i stale si&#281; powi&#281;ksza. Trudno aby tak&#261; sytuacj&#281; nie wykorzysta&#322;y polskie firmy wydawnicze.&lt;/p&gt;


	&lt;p&gt;Jeszcze w grudniu 2006 powinna pojawi&#263; si&#281; w ksi&#281;garniach &lt;a href="http://helion.pl/ksiazki/prruby.htm"&gt;polska wersja&lt;/a&gt; kultowej ksi&#261;&#380;ki na temat Rubiego &amp;#8211; tzw. PickAxe2&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; czyli &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0974514055/"&gt;Programming Ruby: The Pragmatic Programmers&lt;/a&gt;.  Pierwsze wydanie tej ksi&#261;&#380;ki przyczyni&#322;o si&#281; w znacznej mierze do popularyzacji j&#281;zyka poza Japoni&#261;. Jest ono &lt;a href="http://www.ruby-doc.org/docs/ProgrammingRuby/"&gt;dost&#281;pne darmo w internecie&lt;/a&gt;. Cz&#281;&#347;&#263; druga, poza tym, &#380;e jest znacznie obszerniejsza, i uwzgl&#281;dnia nowo&#347;ci w j&#281;zyku w stos. do starego wydania z 1993 roku.&lt;/p&gt;


	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Nazwa PickAxe pochodzi od charakterystycznej ok&#322;adki z kilofem (ang. pick axe) Dw&#243;jka oznacza drugie wydanie.&lt;/p&gt;</description>
      <pubDate>Fri, 01 Dec 2006 01:47:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:1fe1ca52-41f7-4f5b-ac0f-7c365d9a65a7</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/12/01/pickaxe2-po-polsku</link>
      <category>Ruby</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Serwery kontynuacyjne - przysz&#322;o&#347;&#263; webu</title>
      <description>&lt;p&gt;Ka&#380;dy, kto zajmowa&#322; si&#281; kiedykolwiek programowaniem stron internetowych wie, &#380;e protok&#243;&#322; &lt;span class="caps"&gt;HTTP&lt;/span&gt; jest bezstanowy. Innymi s&#322;owy, ka&#380;de prze&#322;adowanie strony  internetowej generuje kompletnie niezale&#380;ne wywo&#322;anie serwera i nie ma on mo&#380;liwo&#347;ci aby powi&#261;za&#263; wywo&#322;anie z konkretnym klientem. Aby temu zaradzi&#263;, wprowadzono prost&#261; sztuczk&#281;. Wprowadzono tzw. mechanizm cookies (dos&#322;. ciasteczek), malutkich plik&#243;w kt&#243;re serwer mo&#380;e wysy&#322;a&#263; do klienta (tam i z powrotem). Ten unikalny identyfikator (sesji)  mo&#380;na te&#380; trzyma&#263; w adresie &lt;span class="caps"&gt;URL&lt;/span&gt;, ale ta metoda jest zdecydowanie odradzana z powodu &#322;atwo&#347;ci nadu&#380;y&#263; (&#322;atwo wykra&#347;&#263; taki numer i podszy&#263; si&#281; pod autora) Od strony klienta jedynym wymaganiem jest aby nie blokowa&#322; sobie w przegl&#261;darce mechanizmu cookies.&lt;/p&gt;


	&lt;p&gt;Serwer znaj&#261;c identyfikator sesji, mo&#380;e zwi&#261;za&#263; z nim szereg danych, np. aktualn&#261; list&#281; zamawianych produkt&#243;w w&#322;o&#380;onych do koszyka w sklepie internetowym. Dane te zwykle trzyma si&#281; w bazie lub w pami&#281;ci operacyjnej. Oczywi&#347;cie czas &#380;ycia danych jest ustalany przez serwet i w normalnym wypadku s&#261; one cyklicznie kasowane. (Z tym &amp;#8220;normalnym&amp;#8221; wypadkiem to r&#243;&#380;nie bywa, bo wiele framework&#243;w tego nie zapewnia i trzeba samemu o to zadba&#263;)&lt;/p&gt;


	&lt;p&gt;Mechanizm sesji jest dosy&#263; wydajny, bo zapytania wysy&#322;ane do serwera mog&#261; by&#263; obs&#322;ugiwane &lt;strong&gt;asynchronicznie&lt;/strong&gt;, czyli bez &#380;adnych blokad w oczekiwaniu na uko&#324;czenie obs&#322;ugi zapytania. Przez lata &amp;#8220;stanowo&#347;&#263;&amp;#8221; protoko&#322;u &lt;span class="caps"&gt;HTTP&lt;/span&gt; zapewnia&#322;o si&#281; w&#322;a&#347;nie za pomoc&#261; sesji.&lt;/p&gt;


	&lt;p&gt;Ten mechanizm ma jednak swoje wady. Najwi&#281;ksz&#261; jest &lt;strong&gt;z&#322;o&#380;ono&#347;&#263;&lt;/strong&gt; jak&#261; wprowadza po stronie skrypt&#243;w na serwerze. (I to nie jest wcale taka trywialna sprawa jak to mo&#380;na by&#322;o zaobserwowa&#263; u developer&#243;w frameworka CherryPy kt&#243;rzy miesi&#261;cami nie potrafili napisa&#263; stabilnie dzia&#322;aj&#261;cego mechanizmu obs&#322;ugi sesji.)&lt;/p&gt;


	&lt;h3&gt;Kontynuacje&lt;/h3&gt;


	&lt;p&gt;Kompletnie innym podej&#347;ciem jest skorzystanie z tzw. mechanizmu kontynuacji.  Mechanizm ten podobny jest do gracza, kt&#243;ry w dowolnym momencie mo&#380;e zapisa&#263; i wczyta&#263; stan gry.  Kontynuacje zapewniaj&#261; taki mechanizm zapisu stanu programu aby w dowolnym momencie p&#243;&#378;niej go przywr&#243;ci&#263;. Niekt&#243;rzy por&#243;wnuj&#261; to do maszyny czasu, bo mo&#380;na w dowolnym momencie przywr&#243;ci&#263; wcze&#347;niejszy stan aplikacji.&lt;/p&gt;


	&lt;p&gt;Zalet z takiego podej&#347;cia jest wiele. We&#378;my np. spraw&#281; obs&#322;ugi &amp;#8220;nie&#347;miertelnego&amp;#8221; przycisku Back w przegl&#261;darce. Obs&#322;uga tego przycisku sprawia spore problemy. Programi&#347;ci najch&#281;tniej w og&#243;le by go zablokowali. W wypadku kontynuacji ten problem w og&#243;le nie istnieje. Klikn&#261;&#322; kto&#347; Back aby cofn&#261;&#263; si&#281; do poprzedniej strony? &#379;aden problem. Serwer przywr&#243;ci ca&#322;y wcze&#347;niejszy stan aplikacji bez &#380;adnego problemu. I to w spos&#243;b &lt;strong&gt;przezroczysty&lt;/strong&gt; dla programisty! Programowanie stron webowych staje si&#281; &lt;strong&gt;znacznie prostsze&lt;/strong&gt;, niczym tworzenie aplikacji desktopowej w&#322;&#261;cznie z debugowaniem krok po kroku. Wg r&#243;&#380;nych prognoz, tak b&#281;dziemy programowa&#263; serwisy internetowe za kilka lat!&lt;/p&gt;


	&lt;p&gt;Sama idea nie jest najwyra&#378;niej jeszcze powszechnie znana, skoro w rozmowie z developerami irlandzkiego Google, zaskoczy&#322;em ich informacj&#261; na ten temat. Kto wie, czy Google mocniej nie zainwestuje w Rubiego (aktualnie mocno korzysta z Pythona, kt&#243;ry jest podstaw&#261; wi&#281;kszo&#347;ci ich skrypt&#243;w).&lt;/p&gt;


	&lt;h3&gt;Smalltalk i Seaside&lt;/h3&gt;


	&lt;p&gt;Smalltalk jest bardzo starym j&#281;zykiem bo jego pocz&#261;tki si&#281;gaj&#261; lat 70-tych. Od zawsze by&#322; j&#281;zykiem w pe&#322;ni obiektowym i dynamicznym. To m.in. Smalltalk pierwszy wymy&#347;li&#322; wirtualn&#261; maszyn&#281; kt&#243;rej to ide&#281; p&#243;&#378;niej skopiowali tw&#243;rcy Javy. W Smalltalku napisano najlepszy (w chwili obecnej) na &#347;wiecie &lt;strong&gt;serwer kontynuacyjny &amp;#8211; &lt;a href="http://www.seaside.st/"&gt;Seaside&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;Czy to spowoduje renesans na Smalltalka? Osobi&#347;cie w to w&#261;tpi&#281;. G&#322;&#243;wn&#261; wad&#261; Smalltalka jest jego monolityczno&#347;&#263; i hermentyczno&#347;&#263;. Uruchamiaj&#261;c &#347;rodowisko Smalltalak uruchamia si&#281; ca&#322;y, zamkni&#281;ty &#347;wiat Smalltalka. Np. nie ma tam dost&#281;pu do plik&#243;w z zewn&#261;trz tak, jak w innych j&#281;zykach. To spowodowa&#322;o, &#380;e j&#281;zyk ten, mimo pewnych sukces&#243;w, nigdy nie zdoby&#322; sobie powszechnego uznania. I moim zdanie, nigdy ju&#380; nie zdob&#281;dzie, bo w mi&#281;dzyczasie wyros&#322;a mu m&#322;oda, obiecuj&#261;ca konkurencja.&lt;/p&gt;


	&lt;h3&gt;Ruby&lt;/h3&gt;


	&lt;p&gt;Ruby jest j&#281;zykiem relatywnie m&#322;odym. Tzn. zosta&#322; po raz pierwszy udost&#281;pniony publicznie w tym samym roku co Java &amp;#8211; 1995. Ale przez wi&#281;kszo&#347;&#263; lat by&#322; ma&#322;o znany poza Japoni&#261; (sk&#261;d pochodzi jego tw&#243;rca).  Ruby jest tak&#380;e  jednym z tych nielicznych j&#281;zyk&#243;w, kt&#243;re (podobnie jak Smalltalk) posiadaj&#261; wbudowan&#261; obs&#322;ug&#281; kontynuacji. Istniej&#261; co prawda r&#243;&#380;ne pr&#243;by implementacji tego mechanizmu w Javie&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;, ale tylko Ruby posiada ten mechanizm jako co&#347; naturalnego i nie trzeba stosowa&#263; &#380;adnych specjalnych sztuczek aby go emulowa&#263;. Z tego co pami&#281;tam, Seaside pierwotnie by&#322; tworzony w Ruby, ale w tamtym okresie, kontynuacje w Ruby by&#322;y jeszcze niedojrza&#322;e, wi&#281;c tw&#243;rcy przerzucili si&#281; na Smalltalka. Ruby jednak szybko si&#281; rozwija, nabiera dojrza&#322;o&#347;ci i moim zdaniem, ma bardzo du&#380;e szanse, aby wyprzedzi&#263; pozosta&#322;e j&#281;zyki przy tworzeniu serwis&#243;w internetowych nowej generacji, serwis&#243;w opartych na kontynuacjach.&lt;/p&gt;


	&lt;h3&gt;Przyk&#322;ad kontynuacji.&lt;/h3&gt;


	&lt;p&gt;Poni&#380;szy przyk&#322;ad&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt; pokazuje implementacj&#281; generatora za pomoc&#261; kontynuacji.&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;Generator&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;
    &lt;span class="ident"&gt;do_generation&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;next&lt;/span&gt;
    &lt;span class="ident"&gt;callcc&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;here&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="attribute"&gt;@main_context&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;here&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
       &lt;span class="attribute"&gt;@generator_context&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

   &lt;span class="ident"&gt;private&lt;/span&gt;

   &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;do_generation&lt;/span&gt;
     &lt;span class="ident"&gt;callcc&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;context&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
       &lt;span class="attribute"&gt;@generator_context&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
       &lt;span class="keyword"&gt;return&lt;/span&gt;
     &lt;span class="keyword"&gt;end&lt;/span&gt;
     &lt;span class="ident"&gt;generating_loop&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;generate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
     &lt;span class="ident"&gt;callcc&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;context&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
       &lt;span class="attribute"&gt;@generator_context&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
       &lt;span class="attribute"&gt;@main_context&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;value&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;A oto oparty na nim generator ci&#261;gu liczb Fibbonacciego:&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;FibGenerator&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Generator&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;generating_loop&lt;/span&gt;
    &lt;span class="ident"&gt;generate&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;a&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;b&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="number"&gt;1&lt;/span&gt;
    &lt;span class="ident"&gt;loop&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;generate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;b&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;b&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;b&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;+&lt;/span&gt;&lt;span class="ident"&gt;b&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="ident"&gt;fib&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;FibGenerator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="number"&gt;15&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="punct"&gt;{&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;&lt;span class="expr"&gt;#{fib.next}&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="comment"&gt;#wynik: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Np. &lt;a href="http://rifers.org/"&gt;Riff&lt;/a&gt; lub &lt;a href="http://jetty.mortbay.org/jetty/"&gt;Jetty 6&lt;/a&gt;.&lt;/p&gt;


	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; Przyk&#322;ad z ksi&#261;&#380;ki &amp;#8220;The Ruby Way&amp;#8221;, 1ed.&lt;/p&gt;</description>
      <pubDate>Wed, 22 Nov 2006 02:26:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:c15ba4a7-3852-452b-af70-9f5ea30a4702</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/11/22/serwery-kontynuacyjne-przysz%C5%82o%C5%9B%C4%87-webu</link>
      <category>Ruby</category>
      <category>Java</category>
      <category>SmallTalk</category>
      <category>ruby</category>
      <category>smalltalk</category>
      <category>java</category>
      <category>continuations</category>
    </item>
    <item>
      <title>Spo&#322;eczno&#347;&#263; Rubiego ro&#347;nie w si&#322;&#281;</title>
      <description>&lt;p&gt;Spo&#322;eczno&#347;&#263; Rubiego jest mo&#380;e mniejsza ni&#380; Pythona, ale jest jaka&#347; bardziej aktywna i zorganizowana (przynajmniej tak to wida&#263; w Polsce). Nie tylko &lt;a href="http://weblog.rubyonrails.pl/articles/2006/09/21/t%C5%82umaczenie-ruby-lang-org-na-j%C4%99zyk-polski"&gt;trwaj&#261; prace&lt;/a&gt; nad t&#322;umaczeniem strony domowej Rubiego na j&#281;zyk polski, ale tak&#380;e coraz cz&#281;&#347;ciej &lt;a href="http://forum.rubyonrails.pl/viewforum.php?id=3"&gt;s&#261; organizowane spotkania&lt;/a&gt; mi&#322;o&#347;nik&#243;w tego j&#281;zyka.&lt;/p&gt;


	&lt;p&gt;Najbli&#380;sze spotkanie jest planowane na &lt;a href="http://forum.rubyonrails.pl/viewtopic.php?id=242"&gt;15 listopada 2006 w Warszawie&lt;/a&gt;. Nied&#322;ugo p&#243;&#378;niej, &lt;a href="http://forum.rubyonrails.pl/viewtopic.php?id=231"&gt;18 listopada&lt;/a&gt; jest organizowane spotkanie w Krakowie.&lt;/p&gt;


	&lt;p&gt;Od niedawna te&#380; oficjalna strona j&#281;zyka Ruby &lt;a href="http://www.ruby-lang.org/pl/"&gt;http://ruby-lang.org&lt;/a&gt; zg&#322;asza si&#281; po polsku (w wypadku przeg&#322;&#261;darki ustawionej na j&#281;z. polski). Inni te&#380; mog&#261; wej&#347;&#263; na stron&#281; polsk&#261;, kt&#243;ra jest bezpo&#347;rednio dost&#281;pna spod adresu: &lt;a href="http://www.ruby-lang.org/pl"&gt;http://www.ruby-lang.org/pl/&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Co ciekawe, zaczyna si&#281; pojawia&#263; coraz wi&#281;cej ofert pracy dla programist&#243;w Rubiego. Oczywi&#347;cie si&#322;&#261; nap&#281;dow&#261; j&#281;zyka jest wci&#261;&#380; &lt;a href="http://rubyonrails.org"&gt;Rails&lt;/a&gt;. :)&lt;/p&gt;</description>
      <pubDate>Wed, 08 Nov 2006 00:34:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:344d9b52-37cd-43c2-a4ee-d4f4358e7ee8</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/11/08/spo%C5%82eczno%C5%9B%C4%87-rubiego-ro%C5%9Bnie-w-si%C5%82%C4%99</link>
      <category>Ruby</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>RadRails i snippety TextMate</title>
      <description>&lt;p&gt;&lt;a href="http://www.radrails.org/"&gt;RadRails&lt;/a&gt;, zintegrowany edytor dla Rubiego i Rails&#243;w zaczyna coraz bardziej niwelowa&#263; wcze&#347;niejsze zachwyty nad komercyjnym edytorem &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt;. Nie do&#347;&#263;, &#380;e jest darmowy i dzia&#322;a na Windows, MacOS-X i Linuksie (TextMate tylko na MacOS-X), to na dodatek uzyska&#322; to, co do tej pory by&#322;o g&#322;&#243;wn&#261; atrakcj&#261; TextMate &amp;#8211; &lt;a href="http://radrailstemplates.com/"&gt;makra przy&#347;pieszaj&#261;ce pisanie kodu, czyli tzw. snippety&lt;/a&gt;. RadRaila ma ju&#380; przygotowanych 199 snippet&#243;w do Rubiego i 50 do &lt;span class="caps"&gt;RHTML&lt;/span&gt;!&lt;/p&gt;


	&lt;p&gt;Do tego wystarczy &lt;a href="http://drnicwilliams.com/2006/08/08/textmate-theme-for-radrails/"&gt;dorzuci&#263; kolorowanie&lt;/a&gt; kodu a&amp;#8217;la TextMate i RadRails ma ju&#380; wszystko (no mo&#380;e do pe&#322;ni doskona&#322;o&#347;ci brakuje mu uzupe&#322;niania kodu tak, jak to robi komercyjny &lt;a href="http://activestate.com/Products/Komodo/?tn=1"&gt;edytor Komodo&lt;/a&gt;)&lt;/p&gt;</description>
      <pubDate>Wed, 08 Nov 2006 00:13:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:0e93ec9d-49e8-4a45-aa9e-374055834917</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/11/08/radrails-i-snippety-textmate</link>
      <category>Ruby on Rails</category>
      <category>Ruby</category>
      <category>radrails</category>
      <category>ruby</category>
      <category>rails</category>
      <category>edytory</category>
    </item>
    <item>
      <title>Polski kana&#322; IRC dla RoR</title>
      <description>&lt;p&gt;Poza polskim &lt;a href="http://forum.rubyonrails.pl/"&gt;forum&lt;/a&gt; mamyod niedawna kana&#322; #rubyonrails.pl na serwerze irc.freenode.net gdzie mo&#380;na bardziej interaktywnie wymienia&#263; si&#281; do&#347;wiadczeniem na temat Rubiego i/lub Rails&#243;w. Na razie nie ma wiele os&#243;b, ale mo&#380;e si&#281; bardziej rozkr&#281;ci.&lt;/p&gt;</description>
      <pubDate>Thu, 12 Oct 2006 16:55:31 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:016c536d-0147-4b2d-bcc3-a4f0e27ffb7e</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/10/12/polski-kana%C5%82-irc-dla-ror</link>
      <category>Ruby on Rails</category>
      <category>Ruby</category>
    </item>
    <item>
      <title>Subversion /etc/init.d script</title>
      <description>&lt;p&gt;Postanowi&#322;em troszk&#281; poprawi&#263; &lt;a href="http://blog.zabiello.com/articles/2006/10/05/ruby-svn-start"&gt;napisany wcze&#347;niej&lt;/a&gt; skrypt startowy do &lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt;. Dorzuci&#322;em te&#380; wersj&#281; w Pythonie.&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="constant"&gt;VERBOSE&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;
&lt;span class="constant"&gt;USER&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;nobody&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;APP&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;/usr/bin/svnserve&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;DIR&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;/home/svn-repository&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;PID&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;/var/run/svnserve.pid&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;script&lt;/span&gt; &lt;span class="ident"&gt;action&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;unless&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;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;%Q|&lt;/span&gt;&lt;span class="string"&gt;su -c &amp;quot;&lt;span class="expr"&gt;#{APP}&lt;/span&gt; -d -r &lt;span class="expr"&gt;#{DIR}&lt;/span&gt;&amp;quot; &lt;span class="expr"&gt;#{USER}&lt;/span&gt;&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;echo `pidof -o %PPID &lt;span class="expr"&gt;#{APP}&lt;/span&gt;` &amp;gt; &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="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;return&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt; &lt;span class="keyword"&gt;unless&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;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;/bin/kill -TERM &lt;span class="expr"&gt;#{File.read(PID)}&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;/bin/rm -f &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="constant"&gt;true&lt;/span&gt;
  &lt;span class="keyword"&gt;end&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;&lt;span class="expr"&gt;#{APP}&lt;/span&gt; &lt;span class="expr"&gt;#{action}&lt;/span&gt;&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;VERBOSE&lt;/span&gt;
  &lt;span class="global"&gt;$defout&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;flush&lt;/span&gt; &lt;span class="comment"&gt;# unbuffered output&lt;/span&gt;
  &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="symbol"&gt;:start&lt;/span&gt;
      &lt;span class="ident"&gt;start&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="symbol"&gt;:stop&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;&lt;span class="expr"&gt;#{File.basename(APP)}&lt;/span&gt; cannot be stopped because it cannot find &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="keyword"&gt;unless&lt;/span&gt; &lt;span class="ident"&gt;stop&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="symbol"&gt;:restart&lt;/span&gt;
      &lt;span class="ident"&gt;stop&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;end&lt;/span&gt;

&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w{&lt;/span&gt;&lt;span class="string"&gt;start stop restart&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="ident"&gt;first&lt;/span&gt;
  &lt;span class="ident"&gt;script&lt;/span&gt; &lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_sym&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;Usage: sudo &lt;span class="expr"&gt;#{__FILE__}&lt;/span&gt; {start|stop|restart}&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;Ten sam skrypt w &lt;strong&gt;Pythonie&lt;/strong&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 python&lt;/span&gt;

&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;os&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;

&lt;span class="constant"&gt;VERBOSE&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;
&lt;span class="constant"&gt;USER&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;nobody&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;APP&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;/usr/bin/svnserve&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;DIR&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;/home/svn-repository&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;PID&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;/var/run/svnserve.pid&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;script&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="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;():&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="keyword"&gt;not&lt;/span&gt; &lt;span class="ident"&gt;os&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="ident"&gt;exists&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;PID&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
      &lt;span class="ident"&gt;os&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;('&lt;/span&gt;&lt;span class="string"&gt;su -c &amp;quot;%s -d -r %s&amp;quot; %s&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="constant"&gt;APP&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="constant"&gt;USER&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
      &lt;span class="ident"&gt;os&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;('&lt;/span&gt;&lt;span class="string"&gt;echo `pidof -o %%PPID %s` &amp;gt; %s&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="constant"&gt;APP&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;PID&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;():&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="keyword"&gt;not&lt;/span&gt; &lt;span class="ident"&gt;os&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="ident"&gt;exists&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;PID&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;False&lt;/span&gt;
    &lt;span class="ident"&gt;os&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;('&lt;/span&gt;&lt;span class="string"&gt;/bin/kill -TERM %s&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="ident"&gt;file&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;PID&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;read&lt;/span&gt;&lt;span class="punct"&gt;())&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;VERBOSE&lt;/span&gt;&lt;span class="punct"&gt;:&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;%s %s&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;APP&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="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
    &lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
  &lt;span class="ident"&gt;elif&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="keyword"&gt;not&lt;/span&gt; &lt;span class="ident"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;():&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;%s cannot be stopped because it cannot find %s&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;os&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="ident"&gt;basename&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;APP&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; &lt;span class="constant"&gt;PID&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;elif&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;restart&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
    &lt;span class="ident"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="ident"&gt;start&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;len&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;argv&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;2&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&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="keyword"&gt;in&lt;/span&gt; &lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;restart&lt;/span&gt;&lt;span class="punct"&gt;'):&lt;/span&gt;
  &lt;span class="ident"&gt;script&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&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="keyword"&gt;else&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;VERBOSE&lt;/span&gt;&lt;span class="punct"&gt;:&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;Usage: sudo %s {start|stop|restart}&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;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Sat, 07 Oct 2006 02:57:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:df9a9b43-95f9-453c-86a0-d8f3b55dd813</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/10/07/svn-start-script</link>
      <category>Python</category>
      <category>Ruby</category>
      <category>ruby</category>
      <category>python</category>
      <category>subversion</category>
    </item>
    <item>
      <title>Ruby i skrypt startowy do SVN</title>
      <description>&lt;p&gt;&lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt; to &#347;wietny, darmowy system wersjonowania kodu. Jest znacznie lepszy od starego &lt;span class="caps"&gt;CVS&lt;/span&gt;&amp;#8217;a. Niestety, nigdzie nie mog&#322;em si&#281; doszuka&#263; skryptu startuj&#261;cego do serwera. Co gorsze, skrytp &lt;em&gt;svnserve&lt;/em&gt; w og&#243;le nie ma opcji zapisu numeru swojego procesu co utrudnia pisanie kodu kt&#243;ry go &amp;#8220;zabije&amp;#8221;. Na szcz&#281;&#347;cie Linux posiada komend&#281; &lt;em&gt;pidof&lt;/em&gt;. Poni&#380;ej gotowy skrypt napisany w Ruby. Nale&#380;y go umie&#347;ci&#263; w /etc/init.d, doda&#263; atrybuty wykonywalno&#347;ci (chmod a+x subversion.rb)  i doda&#263; linki symboliczne aby startowa&#322;a utomatycznie razem ze startem serwera (pod Debianem/Ubuntu robi to komenda update-rc.d -f subversion.rb defaults, pod RedHatem/CentOS/Fedor&#261; jest do tego komenda &lt;em&gt;chkconfig&lt;/em&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="global"&gt;$USER&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;nobody&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="global"&gt;$APP&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;/usr/bin/svnserve&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="global"&gt;$DIR&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;/home/SVN&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="global"&gt;$PID&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;/var/run/svnserve.pid&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;script&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;start&lt;/span&gt; 
    &lt;span class="ident"&gt;system&lt;/span&gt;&lt;span class="punct"&gt;(%Q|&lt;/span&gt;&lt;span class="string"&gt;su -c &amp;quot;&lt;span class="expr"&gt;#{$APP}&lt;/span&gt; -d -r &lt;span class="expr"&gt;#{$DIR}&lt;/span&gt;&amp;quot; &lt;span class="expr"&gt;#{$USER}&lt;/span&gt;&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;(%Q|&lt;/span&gt;&lt;span class="string"&gt;echo `pidof -o %PPID &lt;span class="expr"&gt;#{$APP}&lt;/span&gt;` &amp;gt; &lt;span class="expr"&gt;#{$PID}&lt;/span&gt;&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;def &lt;/span&gt;&lt;span class="method"&gt;stop&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="keyword"&gt;not&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="global"&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;(%Q|&lt;/span&gt;&lt;span class="string"&gt;/bin/kill -TERM &lt;span class="expr"&gt;#{File.read($PID)}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;|)&lt;/span&gt;
    &lt;span class="constant"&gt;true&lt;/span&gt;
  &lt;span class="keyword"&gt;end&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;&lt;span class="expr"&gt;#{$APP}&lt;/span&gt; &lt;span class="expr"&gt;#{action}&lt;/span&gt;...&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="global"&gt;$defout&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;flush&lt;/span&gt; &lt;span class="comment"&gt;# unbuffered output&lt;/span&gt;
  &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt; 
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="symbol"&gt;:start&lt;/span&gt; 
      &lt;span class="ident"&gt;start&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;done&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="symbol"&gt;:stop&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="keyword"&gt;not&lt;/span&gt; &lt;span class="ident"&gt;stop&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;&lt;span class="expr"&gt;#{File.basename($APP)}&lt;/span&gt; cannot be stopped because it cannot find &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="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;done&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;when&lt;/span&gt; &lt;span class="symbol"&gt;:restart&lt;/span&gt;
      &lt;span class="ident"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
      &lt;span class="ident"&gt;start&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;done&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;case&lt;/span&gt; &lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;
  &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;:&lt;/span&gt; &lt;span class="ident"&gt;script&lt;/span&gt; &lt;span class="symbol"&gt;:start&lt;/span&gt;
  &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;:&lt;/span&gt; &lt;span class="ident"&gt;script&lt;/span&gt; &lt;span class="symbol"&gt;:stop&lt;/span&gt;
  &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;restart&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;:&lt;/span&gt; &lt;span class="ident"&gt;script&lt;/span&gt; &lt;span class="symbol"&gt;:restart&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="punct"&gt;%w{&lt;/span&gt;&lt;span class="string"&gt;start stop restart&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="ident"&gt;first&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;Usage: sudo &lt;span class="expr"&gt;#{__FILE__}&lt;/span&gt; {start|stop|restart}&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;exit&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 05 Oct 2006 16:37:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:4d762cf3-fbc0-4ef8-b1ed-82a4d96284ca</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/10/05/ruby-svn-start</link>
      <category>Ruby</category>
      <category>subversion</category>
      <category>ruby</category>
      <category>linux</category>
    </item>
    <item>
      <title>Uniksowy skrypt /etc/init.d w Ruby</title>
      <description>&lt;p&gt;Ruby ca&#322;kiem dobrze nadaje si&#281; do pisania skrypt&#243;w systemowych. W sumie nie wiem dlaczego do tej pory pisa&#322;em skrypty tego typu w uniksowym bash&amp;#8217;u. :)&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="constant"&gt;MONGREL&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;/usr/bin/mongrel_rails&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;PROJECT&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;/home/httpd/somedomain.com/rails_project&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;execute&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="ident"&gt;project&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="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;project&lt;/span&gt;&lt;span class="punct"&gt;)&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;&lt;span class="expr"&gt;#{MONGREL}&lt;/span&gt; &lt;span class="expr"&gt;#{action}&lt;/span&gt;...&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="global"&gt;$defout&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;flush&lt;/span&gt; &lt;span class="comment"&gt;# unbuffered output&lt;/span&gt;
  `&lt;span class="comment"&gt;#{MONGREL} cluster::#{action}`&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;done&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;case&lt;/span&gt; &lt;span class="constant"&gt;ARGV&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;
  &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="ident"&gt;execute&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="constant"&gt;PROJECT&lt;/span&gt;
  &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="ident"&gt;execute&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="constant"&gt;PROJECT&lt;/span&gt;
  &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;restart&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="ident"&gt;execute&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;restart&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="constant"&gt;PROJECT&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="punct"&gt;%w{&lt;/span&gt;&lt;span class="string"&gt;start stop restart&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="ident"&gt;first&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;Usage: sudo &lt;span class="expr"&gt;#{__FILE__}&lt;/span&gt; {start|stop|restart}&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;exit&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 29 Sep 2006 14:04:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:8cb51bb5-b36b-493e-8e04-073e3f28170f</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/09/29/uniksowy-skrypt-etc-init-d-w-ruby</link>
      <category>Ruby</category>
      <category>ruby</category>
      <category>linux</category>
      <category>mongrel</category>
    </item>
  </channel>
</rss>
