<?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: Szybki start z Rails, Merb i Pylons</title>
    <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>moje notatki, linki, komentarze</description>
    <item>
      <title>Szybki start z Rails, Merb i Pylons</title>
      <description>&lt;p&gt;Celem tego tekstu jest por&#243;wnanie podstawowych czynno&#347;ci niezb&#281;dnych do tego aby uruchomi&#263; Rails, Merb oraz Pylons. Zak&#322;adam &#380;e u&#380;ywany b&#281;dzie&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://rubyonrails.org"&gt;Rails&lt;/a&gt; (v2.0.1) + &lt;a href="http://ar.rubyonrails.org/"&gt;Active Record&lt;/a&gt; + &lt;a href="http://haml.hamptoncatlin.com/"&gt;Haml&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://merbivore.com/"&gt;Merb&lt;/a&gt; (v0.4.2)+ &lt;a href="http://code.google.com/p/ruby-sequel/"&gt;Sequel&lt;/a&gt; (v0.4.3) +  &lt;a href="http://haml.hamptoncatlin.com/"&gt;Haml&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://pylonshq.com"&gt;Pylons&lt;/a&gt;  (v0.9.6.1) + &lt;a href="http://sqlalchemy.org"&gt;SQLAlchemy&lt;/a&gt;  + &lt;a href="http://makotemplates.org"&gt;Mako&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Wpierw musimy (je&#347;li jeszcze nie mamy) poinstalowa&#263; stosowne biblioteki. W wypadku Rails i Merba musimy mie&#263; Rubiego i RubyGems oraz doinstalowane gemy:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;gem install -y rails haml merb sequel merb_sequel&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W wypadku Pylons musimy mie&#263; zainstalowanego Pythona oraz pakiet setuptools daj&#261;cy mo&#380;liwo&#347;&#263; u&#380;ywania skryptu easy_install (taki odpowiednik RubyGems dla Pythona)&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;easy_install Pylons SQLAlchemy Mako&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h2&gt;Tworzenie projektu:&lt;/h2&gt;


	&lt;h3&gt;Rails&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;rails rails_app&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Merb&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;merb merb_app&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Pylons&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;paster create -t pylons pylons_app&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h2&gt;Podpi&#281;cie do bazy&lt;/h2&gt;


	&lt;h3&gt;Rails&lt;/h3&gt;


	&lt;p&gt;Nale&#380;y w pliku config/database.yml wpisa&#263;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_yaml "&gt;&lt;span class="key"&gt;shared&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="anchor"&gt;&amp;amp;shared&lt;/span&gt;  
  &lt;span class="key"&gt;adapter&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; mysql
  &lt;span class="key"&gt;encoding&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; utf8
  &lt;span class="key"&gt;username&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; login
  &lt;span class="key"&gt;socket&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; /opt/local/var/run/mysql5/mysqld.sock
  &lt;span class="key"&gt;password&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; haslo
&lt;span class="key"&gt;development&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
  &lt;span class="key"&gt;database&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; rails_app
  &amp;lt;&amp;lt;: *shared
&lt;span class="key"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
  &lt;span class="key"&gt;database&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; test
  &amp;lt;&amp;lt;: *shared
&lt;span class="key"&gt;production&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
  &lt;span class="key"&gt;database&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; rails_app
  &amp;lt;&amp;lt;: *shared&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Merb&lt;/h3&gt;


Tu jest tak samo jak w Rails z t&#261; r&#243;&#380;nic&#261;, &#380;e nie ma tego pliku. Nale&#380;y stworzy&#263; Plik config/database.yml:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_yaml "&gt;&lt;span class="document"&gt;---
  shared: &amp;amp;shared  &lt;/span&gt;
    &lt;span class="symbol"&gt;:adapter&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; mysql
    &lt;span class="symbol"&gt;:encoding&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; utf8
    &lt;span class="symbol"&gt;:username&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; login
    &lt;span class="symbol"&gt;:socket&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; /opt/local/var/run/mysql5/mysqld.sock
    &lt;span class="symbol"&gt;:password&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; haslo
  &lt;span class="key"&gt;development&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="symbol"&gt;:database&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; merb_app
    &amp;lt;&amp;lt;: *shared
  &lt;span class="key"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="symbol"&gt;:database&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; test
    &amp;lt;&amp;lt;: *shared
  &lt;span class="key"&gt;production&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="symbol"&gt;:database&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; merb_app
    &amp;lt;&amp;lt;: *shared&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Pylons&lt;/h3&gt;


	&lt;p&gt;Tu, niestety, jest wi&#281;ksza zabawa, bo zar&#243;wno Pylons jak i SQLAlchemy s&#261; bardziej z&#322;o&#380;one.&lt;/p&gt;


	&lt;p&gt;W pliku development.ini wstawiamy:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;sqlalchemy&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;url&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;mysql&lt;/span&gt;&lt;span class="punct"&gt;:/&lt;/span&gt;&lt;span class="regex"&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="symbol"&gt;:haslo@localhost&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="number"&gt;3306&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;pylons_app&lt;/span&gt;
&lt;span class="ident"&gt;sqlalchemy&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;echo&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;
&lt;span class="ident"&gt;sqlalchemy&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;pool_recycle&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;3600&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Warto zwr&#243;ci&#263; uwag&#281;, &#380;e parametr &amp;#8216;pool_recycle&amp;#8217; zabezpiecza nas przed pewnym problemem w MySQL. Ot&#243;&#380; po paru godzinach nieaktywno&#347;ci, potrafi zrywa&#263; zestawione wcze&#347;niej po&#322;&#261;czenie. SQLAlchemy zabezpiecza si&#281; przed tym stukaj&#261;c do bazy co godzin&#281;. Active Record nie ma przed tym standardowo wbudowanego zabezpieczenia (sic!). Sequel za&#347; (te&#380; &amp;#8211; jak SQLAlchemy- pracuj&#261;cy wielow&#261;tkowo) wy&#322;apuje zerwane po&#322;&#261;czenia, czy&#347;ci je i zestawia z powrotem.&lt;/p&gt;


	&lt;p&gt;Musimy ustawi&#263; sesj&#281; dla SQLAlchemy. Dzia&#322;a i czy&#347;ci si&#281; po ka&#380;dym prze&#322;adowaniu przegl&#261;darki internetowej. W pliku pylons_app/lib/base.py wpisujemy:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# reszta pliku...&lt;/span&gt;
&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;pylons_app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;model&lt;/span&gt; &lt;span class="ident"&gt;as&lt;/span&gt; &lt;span class="ident"&gt;model&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;BaseController(WSGIController):&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;__call__&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;environ&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;start_response&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;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Invoke the Controller&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="ident"&gt;conn&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;config&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;pylons.g&lt;/span&gt;&lt;span class="punct"&gt;'].&lt;/span&gt;&lt;span class="ident"&gt;sa_engine&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;connect&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
        &lt;span class="ident"&gt;model&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;Session&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;conn&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;try&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;WSGIController&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="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;environ&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;start_response&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;finally&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
            &lt;span class="ident"&gt;model&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;Session&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;remove&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
            &lt;span class="ident"&gt;conn&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;close&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
&lt;span class="comment"&gt;# reszta pliku...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;           

	&lt;h2&gt;Tworzenie modeli&lt;/h2&gt;


	&lt;h3&gt;Rails&lt;/h3&gt;


	&lt;p&gt;W Rails korzystamy z wbudowanych generator&#243;w kodu:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_shell "&gt;$ script/generate model User
-&amp;gt; app/models/user.rb
...
-&amp;gt; db/migrate/001_create_users.rb

$ script/generate model Post
-&amp;gt; app/models/post.rb
...
-&amp;gt; db/migrate/002_create_posts.rb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Razem z modelami domy&#347;lnie s&#261; tworzone pliki z migracjami. Wpierw jednak zdefiniujmy relacje mi&#281;dzy modelami:&lt;/p&gt;


	&lt;p&gt;Plik app/models/post.rb:&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;Post&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;
  &lt;span class="ident"&gt;belongs_to&lt;/span&gt; &lt;span class="symbol"&gt;:user&lt;/span&gt;
  &lt;span class="comment"&gt;# Albo to samo za pomoc&#261; tych metod:&lt;/span&gt;
  &lt;span class="comment"&gt;# def user&lt;/span&gt;
  &lt;span class="comment"&gt;#   User.find :first,:conditions =&amp;gt; [&amp;quot;id=?&amp;quot;, id]&lt;/span&gt;
  &lt;span class="comment"&gt;# end&lt;/span&gt;
  &lt;span class="comment"&gt;# def user=(item)  &lt;/span&gt;
  &lt;span class="comment"&gt;#   self.user_id = item.id&lt;/span&gt;
  &lt;span class="comment"&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;Plik app/models/user.rb:&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;User&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;
  &lt;span class="ident"&gt;has_many&lt;/span&gt; &lt;span class="symbol"&gt;:posts&lt;/span&gt;
  &lt;span class="comment"&gt;# Albo to samo bardziej bezpo&#347;rednio:&lt;/span&gt;
  &lt;span class="comment"&gt;# def posts&lt;/span&gt;
  &lt;span class="comment"&gt;#  Post.find :all, :conditions =&amp;gt; [&amp;quot;user_id=?&amp;quot;, id]&lt;/span&gt;
  &lt;span class="comment"&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;Zdefiniujemy nie tylko struktury tabel ale te&#380; wype&#322;nimy je przyk&#322;adowymi danymi.&lt;/p&gt;


	&lt;p&gt;Plik db/migrate/001_create_users.rb:&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;CreateUsers&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&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;self.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="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:force&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="keyword"&gt;do&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="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;string&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;:null&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;add_index&lt;/span&gt; &lt;span class="symbol"&gt;:users&lt;/span&gt;&lt;span class="punct"&gt;,&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="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="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.down&lt;/span&gt;
    &lt;span class="ident"&gt;drop_table&lt;/span&gt; &lt;span class="symbol"&gt;:users&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;Plik db/migrate/001_create_posts.rb:&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;CreatePosts&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&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;self.up&lt;/span&gt;
    &lt;span class="ident"&gt;create_table&lt;/span&gt; &lt;span class="symbol"&gt;:posts&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:force&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="keyword"&gt;do&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="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;integer&lt;/span&gt; &lt;span class="symbol"&gt;:user_id&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:null&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;false&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;string&lt;/span&gt; &lt;span class="symbol"&gt;:title&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:null&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;false&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;text&lt;/span&gt; &lt;span class="symbol"&gt;:body&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;timestamps&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;add_index&lt;/span&gt; &lt;span class="symbol"&gt;:posts&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:title&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;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;new&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;title&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Tytu&#322; artyku&#322;u&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Tre&#347;&#263; artyku&#322;u&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&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="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="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;save!&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;self.down&lt;/span&gt;
    &lt;span class="ident"&gt;drop_table&lt;/span&gt; &lt;span class="symbol"&gt;:posts&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;Uruchamiamy migracje:&lt;/p&gt;


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

	&lt;p&gt;Sprawd&#378;my interaktywnie (w konsoli, czyli po odpaleniu ruby script/console) czy modele dzia&#322;aj&#261; prawid&#322;owo.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt; &lt;span class="symbol"&gt;:all&lt;/span&gt;
&lt;span class="comment"&gt;# =&amp;gt; [#&amp;lt;User id: 1, name: &amp;quot;Jarek&amp;quot;&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;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:first&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;posts&lt;/span&gt;
&lt;span class="comment"&gt;# =&amp;gt; [#&amp;lt;Post id: 1, user_id: 1, title: &amp;quot;Tytu&#322; artyku&#322;u&amp;quot;, body: &amp;quot;Tre&#347;&#263; artyku&#322;u&amp;quot;, created_at: &amp;quot;2007-12-15 18:16:27&amp;quot;, updated_at: &amp;quot;2007-12-15 18:16:27&amp;quot;&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;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:first&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;posts&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;title&lt;/span&gt;
&lt;span class="comment"&gt;# =&amp;gt; &amp;quot;Tytu&#322; artyku&#322;u&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

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


	&lt;p&gt;Tu wpierw trzeba wybra&#263; jaki &lt;span class="caps"&gt;ORM&lt;/span&gt; chcemy u&#380;ywa&#263; (domy&#347;lnie Merb nie ma w&#322;aczonej obs&#322;ugi &#380;adnego). Operacja jest bardzo prosta. W pliku config/dependencies.rb odkomentujemy linijk&#281; tak aby by&#322;o:&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;Modele generujemy identycznymi generatorami jak w Rails.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_shell "&gt;$ script/generate model User
-&amp;gt; app/models/user.rb
...
-&amp;gt; schema/migrations/001_add_model_users.rb

$ script/generate model Post
-&amp;gt; app/models/post.rb
...
-&amp;gt; schema/migrations/002_add_model_posts.rb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Definicja modeli.&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;Post&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;Model&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:posts&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;one_to_one&lt;/span&gt; &lt;span class="symbol"&gt;:user&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:from&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:Post&lt;/span&gt;
  &lt;span class="comment"&gt;# To samo co:&lt;/span&gt;
  &lt;span class="comment"&gt;# def user&lt;/span&gt;
  &lt;span class="comment"&gt;#   User.filter(:id=&amp;gt; user_id).first&lt;/span&gt;
  &lt;span class="comment"&gt;# end  &lt;/span&gt;
  &lt;span class="comment"&gt;# def user=(obj)&lt;/span&gt;
  &lt;span class="comment"&gt;#   self.user_id = obj.id&lt;/span&gt;
  &lt;span class="comment"&gt;# end  &lt;/span&gt;
  &lt;span class="comment"&gt;#&lt;/span&gt;
  &lt;span class="comment"&gt;# Merb nie ma automagicznego wype&#322;niania tre&#347;ci&#261;&lt;/span&gt;
  &lt;span class="comment"&gt;# p&#243;l o nazwach created_at czy updated_at&lt;/span&gt;
  &lt;span class="comment"&gt;# Ale posiada wywo&#322;ania zwrotne (te&#380; jak Rails)&lt;/span&gt;
  &lt;span class="ident"&gt;after_create&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;set&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:created_at&lt;/span&gt; &lt;span class="punct"&gt;=&amp;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;set&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:updated_at&lt;/span&gt; &lt;span class="punct"&gt;=&amp;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="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;after_update&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;set&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:updated_at&lt;/span&gt; &lt;span class="punct"&gt;=&amp;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="keyword"&gt;end&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;User&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;Model&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:users&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;one_to_many&lt;/span&gt; &lt;span class="symbol"&gt;:posts&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:from&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:posts&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:key&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:user_id&lt;/span&gt;
  &lt;span class="comment"&gt;# To samo co:&lt;/span&gt;
  &lt;span class="comment"&gt;# def posts&lt;/span&gt;
  &lt;span class="comment"&gt;#   Post.filter :user_id =&amp;gt; pk&lt;/span&gt;
  &lt;span class="comment"&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 przeciwie&#324;stwie do Active Record, w Sequelu mo&#380;na zdefiniowa&#263; (&lt;a href="http://code.google.com/p/ruby-sequel/wiki/SequelModels"&gt;metod&#261; set_schema&lt;/a&gt;) struktur&#281; tabel w modelu (wtedy nie trzeba np. zagl&#261;da&#263; do migracji ani bazy, aby sobie przypomnie&#263; struktur&#281; tabeli). Ale aby oszcz&#281;dzi&#263; sobie pisania, zda&#322;em si&#281; tu na automatyczne rozpoznanie struktury tabel przez Rubiego.&lt;/p&gt;


	&lt;p&gt;Teraz pora na migracje. Sequel te&#380; je posiada, cho&#263; r&#243;&#380;ni&#261; si&#281; troszk&#281; sk&#322;adni&#261; do tych w Active Record.&lt;/p&gt;


	&lt;p&gt;Plik schema/migrations/001_add_mode_users.rb:&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;AddModelUsers&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;primary_key&lt;/span&gt; &lt;span class="symbol"&gt;:id&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;:size&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;255&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="keyword"&gt;end&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="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;'&lt;/span&gt;&lt;span class="string"&gt;DROP TABLE users&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Plik schema/migrations/002_add_mode_posts.rb:&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;AddModelPosts&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;:posts&lt;/span&gt; &lt;span class="keyword"&gt;do&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="ident"&gt;integer&lt;/span&gt; &lt;span class="symbol"&gt;:user_id&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:null&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;
      &lt;span class="ident"&gt;varchar&lt;/span&gt; &lt;span class="symbol"&gt;:title&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:null&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;false&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;text&lt;/span&gt; &lt;span class="symbol"&gt;:body&lt;/span&gt;
      &lt;span class="ident"&gt;datetime&lt;/span&gt; &lt;span class="symbol"&gt;:created_at&lt;/span&gt; 
      &lt;span class="ident"&gt;datetime&lt;/span&gt; &lt;span class="symbol"&gt;:updated_at&lt;/span&gt; 
    &lt;span class="keyword"&gt;end&lt;/span&gt;    
    &lt;span class="ident"&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;new&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;title&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Tytu&#322; artyku&#322;u&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Tre&#347;&#263; artyku&#322;u&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&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;filter&lt;/span&gt;&lt;span class="punct"&gt;(&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="string"&gt;Jarek&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;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;save&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;'&lt;/span&gt;&lt;span class="string"&gt;DROP TABLE posts&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Uruchomienie migracji dzia&#322;a w Sequelu tak samo jak w Active Record (nawet parametr &lt;span class="caps"&gt;VERSION&lt;/span&gt; te&#380; tu dzia&#322;a).&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;No to pora na test z interaktywnej konsoli. Odpala si&#281; j&#261; przez:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;merb -i&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&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="comment"&gt;# =&amp;gt; [#&amp;lt;User:0x19477e8 @changed_columns=[], @values={:name=&amp;gt;&amp;quot;Jarek&amp;quot;, :id=&amp;gt;1}, newfalse]&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;first&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;posts&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="keyword"&gt;class 
&lt;/span&gt;&lt;span class="class"&gt;#&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;Sequel&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;MySQL&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;Dataset&lt;/span&gt;
&lt;span class="comment"&gt;# User.first.posts.sql&lt;/span&gt;
&lt;span class="comment"&gt;# =&amp;gt; &amp;quot;SELECT * FROM posts WHERE (`user_id` = 1)&amp;quot;        &lt;/span&gt;
&lt;span class="ident"&gt;User&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;posts&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;title&lt;/span&gt;
&lt;span class="comment"&gt;# =&amp;gt; &amp;quot;Tytu\305\202 artyku\305\202u&amp;quot;      &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Sequel nie tylko jest szybszy i u&#380;ywa iterator&#243;w (oszcz&#281;dzaj&#261;&#263; przez to pami&#281;&#263;). Jest te&#380; wielow&#261;tkowy (u&#380;ywa puli w&#261;tk&#243;w) oraz pozwala na krokowy podgl&#261;d kodu &lt;span class="caps"&gt;SQL&lt;/span&gt; &lt;strong&gt;przed&lt;/strong&gt; jakimkolwiek przeslaniem kwerendy do bazy danych. Sequel r&#243;wnie&#380; nie zwraca liste obiektow &lt;span class="caps"&gt;ORM&lt;/span&gt; z bazy (jak Active Record) ale jeden, specjalny obiekt proxy. Pozwala to na interaktywne budowanie kodu w stopniu o wiele lepszym ni&#380; pozwala na to Active Record (czy nawet  DataMapper). Sequel ma r&#243;wnie&#380; &lt;a href="http://code.google.com/p/ruby-sequel/wiki/SequelModels"&gt;wbudowany cache modeli&lt;/a&gt; wsp&#243;&#322;pracuj&#261;cy z szybkim serwerem memcached.&lt;/p&gt;


	&lt;h3&gt;Pylons&lt;/h3&gt;


	&lt;p&gt;Poni&#380;sza konfiguracja jest inspirowana tekstem &lt;a href="http://wiki.pylonshq.com/display/pylonscookbook/SQLAlchemy+0.4+for+people+in+a+hurry"&gt;SQLAlchemy 0.4 for people in a hurry&lt;/a&gt;. Pylons nie wymaga aby ka&#380;dy model by&#322; w oddzielnym pliku, zatem u&#380;yjemy jednego. W pliku pylons_app/model/&lt;i&gt;init&lt;/i&gt;.py wpisujemy:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# -*- coding: utf8 -*-&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;datetime&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;datetime&lt;/span&gt;

&lt;span class="comment"&gt;# Zgodnie z filozofi&#261; Pythona, importujemy tylko tylko interesuj&#261;ce nas symbole&lt;/span&gt;
&lt;span class="comment"&gt;# aby nie za&#347;mieca&#263; sobie przestrzeni nazw:&lt;/span&gt;

&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;pylons&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;config&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;sqlalchemy&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;ForeignKey&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;Column&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;MetaData&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;Table&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;types&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;sqlalchemy&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;orm&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;mapper&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;relation&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;sqlalchemy&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;orm&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;scoped_session&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;sessionmaker&lt;/span&gt;

&lt;span class="constant"&gt;Session&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;scoped_session&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sessionmaker&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;autoflush&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;span class="ident"&gt;transactional&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;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;config&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;pylons.g&lt;/span&gt;&lt;span class="punct"&gt;'].&lt;/span&gt;&lt;span class="ident"&gt;sa_engine&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
&lt;span class="ident"&gt;metadata&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;MetaData&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;

&lt;span class="comment"&gt;# Tworzymy definicje tabel:&lt;/span&gt;

&lt;span class="ident"&gt;table_users&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Table&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;users&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;metadata&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
  &lt;span class="constant"&gt;Column&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;types&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;Integer&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;primary_key&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;span class="constant"&gt;Column&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;types&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;String&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;255&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
  &lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="ident"&gt;table_posts&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Table&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;posts&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;metadata&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
  &lt;span class="constant"&gt;Column&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;types&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;Integer&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;primary_key&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;span class="constant"&gt;Column&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;user_id&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;types&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;Integer&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ForeignKey&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;users.id&lt;/span&gt;&lt;span class="punct"&gt;')),&lt;/span&gt;
  &lt;span class="ident"&gt;Column&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;title&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;types&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;Unicode&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;255&lt;/span&gt;&lt;span class="punct"&gt;)),&lt;/span&gt;
  &lt;span class="ident"&gt;Column&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;body&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;types&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;Unicode&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt;
  &lt;span class="ident"&gt;Column&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;created_at&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;types&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;DateTime&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;default&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;datetime&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="constant"&gt;Column&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;updated_at&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;types&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;DateTime&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;default&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;datetime&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="punct"&gt;)&lt;/span&gt;
&lt;span class="comment"&gt;# Zamiast tego mo&#380;na automatycznie wci&#261;gn&#261;&#263; istniej&#261;c&#261; struktur&#281;:&lt;/span&gt;
&lt;span class="comment"&gt;#&lt;/span&gt;
&lt;span class="comment"&gt;# table_users = Table('users', metadata, autoload=True)&lt;/span&gt;
&lt;span class="comment"&gt;# table_posts = Table('posts', metadata, autoload=True)&lt;/span&gt;

&lt;span class="comment"&gt;# Tworzymy definicje modeli.&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;User(object):&lt;/span&gt;
    &lt;span class="ident"&gt;pass&lt;/span&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Post(object):&lt;/span&gt;
    &lt;span class="ident"&gt;pass&lt;/span&gt;

&lt;span class="comment"&gt;# Mapowanie ORM do klas SQLAlchemy i ustawienie&lt;/span&gt;
&lt;span class="comment"&gt;# relacji jeden-do-wielu&lt;/span&gt;
&lt;span class="ident"&gt;mapper&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;table_users&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;properties&lt;/span&gt;&lt;span class="punct"&gt;={'&lt;/span&gt;&lt;span class="string"&gt;posts&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="symbol"&gt;:relation&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;backref&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;')})&lt;/span&gt;
&lt;span class="ident"&gt;mapper&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;table_posts&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Wygl&#261;da to bardziej skomplikowanie, ale SQLAlchemy ma te&#380; wi&#281;ksze mo&#380;liwo&#347;ci. Zasadnicz&#261; r&#243;&#380;nic&#261; w SQLAlchemy jest rozdzielenie obiekt&#243;w &lt;span class="caps"&gt;ORM&lt;/span&gt; od obiekt&#243;w modelu biznesowego. Obiekty &lt;span class="caps"&gt;ORM&lt;/span&gt; zajmuj&#261; si&#281; mapowaniem struktur tabel do obiekt&#243;w Pythona. S&#261; one nast&#281;pnie &#322;&#261;czone z klasami SQLAlchemy. Takie rozdzielenie daje du&#380;o wi&#281;ksze mo&#380;liwo&#347;ci, bo mo&#380;na w modelu biznesowym nawet zamapowa&#263; kilka tabel do jednego modelu. SQLAlchemy ma du&#380;o innych mo&#380;liwo&#347;ci, o kt&#243;rych tu nie b&#281;d&#281; teraz pisa&#263;. W ka&#380;dym razie odbija si&#281; to na z&#322;o&#380;ono&#347;ci (ale i tak to jest pro&#347;ciej ni&#380; np. w javowym Hibernate).&lt;/p&gt;


	&lt;p&gt;Co z migracjami? Nie ma ich. Trzeba by by&#322;o je napisa&#263; (to w sumie nie jest trudna sprawa). Stworzmy jednak strukture tabel wraz z przyk&#322;adowymi danymi za pomoc&#261; SQLAlchemy. W tym celu ko&#324;c&#243;wka pliku pylons_app/websetup.py powinna wygl&#261;da&#263; nast&#281;puj&#261;co:&lt;/p&gt;


# pocz&#261;tek pliku&amp;#8230;
&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;setup_config&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;command&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;filename&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;section&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;vars&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;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Place any commands to setup pylons_app here&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;conf&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;appconfig&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;config:&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;filename&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;load_environment&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;conf&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;global_conf&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;conf&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;local_conf&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;pylons_app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;model&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;metadata&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;Session&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="constant"&gt;Post&lt;/span&gt;

    &lt;span class="ident"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;info&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Creating tables&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="ident"&gt;metadata&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;create_all&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;config&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;pylons.g&lt;/span&gt;&lt;span class="punct"&gt;'].&lt;/span&gt;&lt;span class="ident"&gt;sa_engine&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;info&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Successfully setup&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;

    &lt;span class="ident"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;info&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Adding some data to table 'users'&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="ident"&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;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;=&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="constant"&gt;Session&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;save&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="constant"&gt;Session&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;commit&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;

    &lt;span class="ident"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;info&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Adding some data to table 'posts'&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="ident"&gt;user_query&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Session&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;query&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;user_id&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;user_query&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;filter&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;name&lt;/span&gt; &lt;span class="punct"&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="ident"&gt;one&lt;/span&gt;&lt;span class="punct"&gt;().&lt;/span&gt;&lt;span class="ident"&gt;id&lt;/span&gt;
    &lt;span class="ident"&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;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;title&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Tytu&#322; artyku&#322;u&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Tre&#347;&#263; artyku&#322;u&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;user_id&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;user_id&lt;/span&gt;
    &lt;span class="constant"&gt;Session&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;save&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="constant"&gt;Session&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;commit&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;    
    &lt;span class="ident"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;info&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Data added.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W powy&#380;szym przyk&#322;adzie wida&#263; te&#380; pr&#243;bk&#281; sposobu w jaki u&#380;ywa si&#281; SQLAlchemy. Ka&#380;da operacja jest zamykana w ramach specjalnej sesji a sesja jest tworzona niezale&#380;nie dla ka&#380;dego w&#261;tku. W SQLAlchemy praktycznie w og&#243;le nie ma potrzeby si&#281;gania do kodu &lt;span class="caps"&gt;SQL&lt;/span&gt; tak jak to nagminnie wida&#263; w Active Record. Cho&#263; musz&#281; te&#380; przyzna&#263;, &#380;e Sequel tak&#380;e &#322;adnie daje sobie rad&#281; ze skomplikowanymi konstrukcjami bez konieczno&#347;ci uciekania si&#281; do surowego kodu &lt;span class="caps"&gt;SQL&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Uruchamiamy tworzenie tabel za pomoc&#261;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;paster setup-app development.ini&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Interaktywny shell uruchamia si&#281; przez&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;paster shell&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Trzeba pami&#281;ta&#263;, &#380;e fakt uruchomienia konsoli nie oznacza, &#380;e mamy automatycznie powci&#261;gane modu&#322;y wszystkich modeli. W Pythonie nie ma magii, wszystko nale&#380;y jawnie zaimportowa&#263;. Tak&#380;e i nasz projekt.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;pylons_app&lt;/span&gt; &lt;span class="ident"&gt;import&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;model&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;User&lt;/span&gt;
&lt;span class="comment"&gt;# =&amp;gt; &amp;lt;class 'pylons_app.model.User'&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h2&gt;Tworzenie kontrolera i prostego widoku.&lt;/h2&gt;


	&lt;h3&gt;Rails&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;script/generate controller home
# =&amp;gt; app/controllers/home_controller.rb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Plik kontrolera (app/controller/home_controller.rb):&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;HomeController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;index&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&lt;/span&gt; &lt;span class="symbol"&gt;:first&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;Aby u&#380;y&#263; Haml zamiast ERb musimy w katalogu projektu odpali&#263; komend&#281; (nie zapomnij o kropce, kt&#243;ra oznacza tu bie&#380;&#261;cy katalog):&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;haml --rails .&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Plik widok (app/views/home/index.html.haml):&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haml "&gt;U&#380;ytkownik
= @user.name
posiada post(y)
%ul
  - @user.posts.each do |post|
    %li= post.title&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Serwer uruchamiamy klasycznie&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;script/server&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Merb&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;script/generate controller home
# =&amp;gt; app/controllers/home.rb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

Plik kontrolera (app/controllers/home.r):
&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;Home&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="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;index&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;first&lt;/span&gt;
    &lt;span class="ident"&gt;render&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;Aby uaktywni&#263; Haml nale&#380;y w pliku config/merb_init.rb dopisa&#263; na ko&#324;cu&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;Template&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Haml&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Warto te&#380; doinstalowa&#263; gemy:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;gem install -y merb_helpers merb_has_rails_plugins ruby-debug&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;i doda&#263; je do config/dependencies.rb&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;dependency&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;merb_helpers&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;dependency&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;merb_has_rails_plugins&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;dependency&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;ruby-debug&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Dzi&#281;ki temu b&#281;dziemy mieli dost&#281;pnych troch&#281; dodatkowych helper&#243;w  z Rails. Za&#347; gem ruby-debug umo&#380;liwia nam wpisanie w dowolnym miejscu komendy 
debugger przerywaj&#261;cej prac&#281; przegl&#261;darki i kieruj&#261;cej wykonanie kodu do konsoli. Po jej zako&#324;czeniu przegl&#261;darka wznawia obs&#322;ug&#281; requestu. Dzia&#322;a to tu tak jak w Rails. Mo&#380;na interaktywnie sobie operowa&#263; na &#380;ywym kodzie. Warto te&#380; wiedzie&#263;, &#380;e w Merb wszystkie pluginy s&#261; po prostu gemami. U&#322;atwia to zarz&#261;dzanie ich wersjami.&lt;/p&gt;


	&lt;p&gt;Plik widoku jest identyczny jak w wy&#380;ej dla Railsow wi&#281;c nie b&#281;d&#281; podawa&#322; jeszcze raz jego tre&#347;ci.&lt;/p&gt;


	&lt;p&gt;Odpalamy serwer za pomoc&#261; komendy &lt;em&gt;merb&lt;/em&gt; i na stronie http://localhost:4000/home podziwiamy wynik. :) Komenda merb&amp;#8212;help wy&#347;wietli wszystkie, dost&#281;pne opcje.&lt;/p&gt;


	&lt;h3&gt;Pylons&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;paster controller home
# =&amp;gt; pylons_app/controllers/home.py&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Plik kontrolera (pylons_app/controllers/home.py):&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;logging&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;pylons_app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;lib&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;base&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;
&lt;span class="ident"&gt;log&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;logging&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getLogger&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;)&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;pylons_app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;model&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;Session&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;User&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;HomeController(BaseController):&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;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
        &lt;span class="ident"&gt;user_query&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Session&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;query&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;c&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;user&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;user_query&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;filter&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;name&lt;/span&gt; &lt;span class="punct"&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="ident"&gt;one&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
        &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;render&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;/home/index.mako&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Plik widoku (pylons_app/templates/home/index.mako):&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_mako "&gt;U&#380;ytkownik ${c.user.name} posiada post(y)
&amp;lt;ul&amp;gt;
  % for post in c.user.posts:
    &amp;lt;li&amp;gt;${post.title}&amp;lt;/li&amp;gt;
  % endfor
&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Odpalamy serwer za pomoc&#261;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_bash "&gt;paster serve development.ini --reload&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Pylons nie posiada tryb&#243;w pracy tak jak Rails czy Merb. Wielow&#261;tkowy serwer &lt;span class="caps"&gt;HTTP&lt;/span&gt; (paster) musi dosta&#263; odpowiedni plik konfiguracyjny. Daje to w sumie wi&#281;cej mo&#380;liwo&#347;ci, bo mo&#380;na izolowa&#263; sobie r&#243;&#380;ne konfiguracje du&#380;o bardziej ni&#380; prosty podzia&#322; na tryb produkcyjny i rozwojowy.&lt;/p&gt;


	&lt;h2&gt;Podsumowanie.&lt;/h2&gt;


	&lt;p&gt;Rails jest bardzo bogato wyposa&#380;ony w r&#243;&#380;ne helpery, posiada dobr&#261; literatur&#281;, ksi&#261;&#380;ki itd. Jest te&#380; bardzo &#322;atwy do nauki i dosy&#263; intuicyjny. Je&#347;li chodzi o prototypowanie, to jest prawie nie do pobicia. Niestety, mo&#380;na si&#281; przyczepi&#263; do jako&#347;ci implementacji wewn&#281;trznej jak i do niekt&#243;rych &lt;a href="http://blog.zabiello.com/articles/2007/12/13/slabosci-active-record"&gt;b&#322;&#281;d&#243;w projektowych w Active Record&lt;/a&gt;. My&#347;l&#281;, &#380;e Railsom wyr&#243;s&#322; bardzzo gro&#378;ny konkurent w postaci Merba. Jest lepiej zorganizowany, sp&#243;jniejszy i szybszy. Jest te&#380; tak samo prosty i intuicyjny. Czy warto si&#281; przesiada&#263;? Wg mnie &amp;#8211; warto. Je&#347;li za&#347; chodzi o &lt;span class="caps"&gt;ORM&lt;/span&gt;, to Sequel jest pod wieloma wzgl&#281;dami lepszym projektem od Active Record. Tu mo&#380;e tego nie eksponowa&#322;em, ale Sequel pozwala na obiektowe budowanie znacznie bardziej skomplikowanych zapyta&#324; ni&#380; to potrafi Active Record czy DataMapper. Po przyk&#322;ady kodu Sequela odsy&#322;am do jego &lt;a href="http://code.google.com/p/ruby-sequel/"&gt;strony domowej&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Co z Pylons? Korzysta z pot&#281;&#380;nego &lt;span class="caps"&gt;ORM&lt;/span&gt;&amp;#8217;a i pot&#281;&#380;nych szablon&#243;w. Ma pe&#322;n&#261; obs&#322;ug&#281; Unicode, szablony Mako natywnie pracuj&#261; na obiektach unikodowych (nie myli&#263; ze stringami utf8). Mako maj&#261; dziedziczenie, pot&#281;&#380;ny, elastyczny cache i s&#261; bardzo &amp;#8220;pythonic&amp;#8221; w swym podej&#347;ciu do budowania modu&#322;&#243;w czy custom tag&#243;w. Niestety Pylons w ca&#322;o&#347;ci wymaga troch&#281; wi&#281;cej wiedzy i umiej&#281;tno&#347;ci aby go ustawi&#263; do pracy. Rails i Merb s&#261; tu znacznie prostsze. Dzi&#281;ki za&#347;  Merb przepa&#347;&#263; mi&#281;dzy wydajno&#347;ci&#261; i mo&#380;liwo&#347;ciami pythonowego Pylonso a frameworkami Rubiego mocno si&#281; zmniejszyla. Ci, co czepiali si&#281; wcze&#347;niej wydajno&#347;ci Rails nie maj&#261; teraz specjalnie na co narzeka&#263;. Ci co narzekali na ograniczenia Active Record, nie maj&#261; wym&#243;wki w zetkni&#281;ciu z Sequelem. No chyba, &#380;e kto&#347; nie chce si&#281; uczy&#263; Rubiego, jego sprawa. Ja jednak uwa&#380;am, &#380;e Ruby to pi&#281;kny j&#281;zyk i bardzo przyjemnie si&#281; w nim pisze. A prostota Merba w por&#243;wnaniu z Pylons jest (szczeg&#243;lnie dla os&#243;b zaczynaj&#261;cych prac&#281;) &amp;#8211; powalaj&#261;ca.&lt;/p&gt;


	&lt;p&gt;Celem tego tekstu by&#322;o pom&#243;c osobom w pocz&#261;tkowej fazie konfiguracji Pylons oraz Merb. Mam nadziej&#281;, &#380;e by&#322; pomocny i dalej ju&#380; ka&#380;dy sobie sam da rad&#281;. Je&#347;li chodzi o dodatkow&#261; pomoc, to warto zajrze&#263; na &lt;span class="caps"&gt;IRC&lt;/span&gt;. Na serwerze freeenode istniej&#261; kana&#322;y: #pylons, #merb, #sequel, #datamapper, #rubyonrails oraz  nasze polskie #rubyonrails.pl i #python-pl. S&#261; te&#380; polskie grupy dyskusyjne w Usenecie: news://pl.comp.lang.python i news://pl.comp.lang.ruby.&lt;/p&gt;


&lt;hr /&gt;

	&lt;p&gt;Kod &#378;r&#243;d&#322;owy z powy&#380;szymi przyk&#322;adami &lt;a href="http://blog.zabiello.com/files/szybki-start.zip"&gt;mo&#380;na pobra&#263; st&#261;d&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 16 Dec 2007 07:31:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:2a1dd95d-df5f-466d-bce9-87eb2b231833</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons</link>
      <category>rails</category>
      <category>merb</category>
      <category>pylons</category>
      <category>sqlalchemy</category>
      <category>mako</category>
      <category>sequel</category>
      <category>activerecord</category>
      <category>ruby</category>
      <category>python</category>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by g00fy-</title>
      <description>&lt;p&gt;@Jaros&#322;aw Zabie&#322;&#322;o
w SQLAlchemy tez mozna przekazywac nazwe tabeli jako relacje. dostepne sa 3 mozliwosci:&lt;/p&gt;


	&lt;p&gt;Obiekt (jesli istnieje, i istnieje FK)
&amp;#8220;Obiekt&amp;#8221; (sqla samo znajdzie pole po FK)
Obiekt.id (podajemy po jakim polu ma joinowac)
Obiekt,obiekt_tabela.c.id 
&amp;#8220;tabela_w_bazie.pole&amp;#8221;&lt;/p&gt;


	&lt;p&gt;mowie oczywiscie o sqlalchemy 0.5
&lt;a href="http://www.sqlalchemy.org/docs/05/documentation.html#docstrings_sqlalchemy" rel="nofollow"&gt;http://www.sqlalchemy.org/docs/05/documentation.html#docstrings_sqlalchemy&lt;/a&gt;.orm_modfunc_relation&lt;/p&gt;</description>
      <pubDate>Wed, 08 Oct 2008 00:08:20 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:beb592a5-7df0-4a79-b6d8-7454bb31d3d1</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1832</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by Jeffar</title>
      <description>&lt;p&gt;Pr&#243;bowa&#322;em wykona&#263; przyk&#322;ad dla Pylons&#243;w, ale okaza&#322;o si&#281;, &#380;e jednego z element&#243;w brakuje. Musia&#322;em jeszcze edytowa&#263; plik config/environment.py, doda&#263; w nim import sqlalchemy as sa oraz config[&amp;#8216;pylons.g&amp;#8217;].sa_engine = sa.engine_from_config(config, &amp;#8216;sqlalchemy.&amp;#8217;). Dopiero to pozwoli&#322;o przej&#347;&#263; przez &amp;#8220;paster setup-app development.ini&amp;#8221;.&lt;/p&gt;</description>
      <pubDate>Wed, 16 Jan 2008 16:37:17 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:5430f3da-5222-452c-bafc-8cd54080d671</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1372</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by Michal</title>
      <description>&lt;p&gt;Czy WSGIController.&lt;i&gt;call&lt;/i&gt;(self, environ, start_response) nie mozna by zapisac prosciej: self(environ, start_response)?&lt;/p&gt;</description>
      <pubDate>Mon, 07 Jan 2008 12:45:39 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:b1462902-29be-44ad-a732-fe32bffce5c4</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1343</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by pnowak</title>
      <description>&lt;p&gt;NO i niestety okaza&#322;o si&#281;, &#380;e migracja w sequel rename_column nie dzia&#322;a transparentnie dla wszystkich baz, i poki co w migracji rename_column trzeba tez podac jej typ jesli uzywamy mysql.. coz taka specyfika mysql. mozna to zrobic przez dodatkowe zapytanie, ale team sequel mowi ze najpierw musza zrobic porzadne narzedzie do introspekcji tabel.&lt;/p&gt;</description>
      <pubDate>Mon, 17 Dec 2007 09:46:35 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:59e01148-59b8-45d6-b35e-40ee97387281</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1304</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by pnowak</title>
      <description>&lt;p&gt;Dzi&#347; wychodzi Sequel 0.4.4, po zmianach o kt&#243;re prosi&#322;em wczoraj. Dojd&#261; nowe metody do migracji (add, rename, drop column), ,tego brakowalo. na ta chwile jeszcze sa bledy z mysql, mam nadzieje ze rozwiazo je szybko, jakis gosc juz nad tym siedzi, pozdr.&lt;/p&gt;</description>
      <pubDate>Mon, 17 Dec 2007 09:32:37 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:dbd247cf-98d6-43fd-afd6-d4b74b6d815f</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1303</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by Dentharg</title>
      <description>&lt;p&gt;Ja to bym jeszcze ch&#281;tnie widzia&#322;, jak przyk&#322;adnie te appy odpali&#263; przy pomocy FCGI&amp;#8230;&lt;/p&gt;</description>
      <pubDate>Mon, 17 Dec 2007 08:24:52 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:0d52ab31-7038-4174-b865-03a48f69ea62</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1302</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;Poprawi&#322;em przyk&#322;ady i &lt;a href="http://blog.zabiello.com/files/szybki-start.zip" rel="nofollow"&gt;kod do pobrania&lt;/a&gt;. W Sequel 0.4.3 poprawili spos&#243;b dodawania rekord&#243;w w relacji one_to_one. Nie przekazuje si&#281; ju&#380; id, ale ca&#322;y obiekt Sequel::Dataset, gdzie jego id jest wy&#322;uskiwany.&lt;/p&gt;</description>
      <pubDate>Mon, 17 Dec 2007 01:36:24 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:9131ebcb-357e-44b0-8ac7-6f86d93954e0</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1301</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;@climbus: nie widz&#281; w konsoli Pylons modeli bez jawnego ich zaimportowania. Co do tych problem&#243;w z relacjami, to mia&#322;em kiedy&#347; podobny problem w Django ORM. ORM&amp;#8217;y Rubiego &#322;adnie to obchodz&#261;. Podczas tworzenia relacji przekazywany jest symbol lub string z nazw&#261; tabeli a nie jej obiekt. Wtedy kolejno&#347;&#263; &#322;adowania nie ma znaczenia bo i tak ten kod jest odpalany z op&#243;&#378;nieniem.&lt;/p&gt;</description>
      <pubDate>Sun, 16 Dec 2007 20:41:11 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:2bc15877-1932-4538-98de-6274d69e78fb</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1299</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by climbus</title>
      <description>&lt;p&gt;Co do rekursywnego importu to jest z tym problem ale g&#322;ownie wychodzi przy skomplikowanych mapowaniach.&lt;/p&gt;


	&lt;p&gt;Obecnie robi&#281; do&#347;&#263; zakr&#281;cone mapowanie (ju&#380; jest 55 tabel) i si&#281; naci&#261;&#322;em na problemy z importami. Og&#243;lnie chodzi o wzajemne powi&#261;zania. Np u&#380;ytkownik posiada artykuly, artykuly posiadaj&#261; komentarze, komentarze nale&#380;&#261; do u&#380;ytkownika. U uzytkownicy.py trzeba wci&#261;gn&#261;&#263; artykuly.py, w arykuly.py wci&#261;gane s&#261; komentarze.py, komentarze.py musz&#261; wciagn&#261;&#263; uzytkownicy.py, ale jeste&#347;my w trakcie budowy modu&#322;u u&#380;ytkownicy.py wi&#281;c nie mo&#380;e jeszcze jego wci&#261;gn&#261;&#263;.&lt;/p&gt;


	&lt;p&gt;Nie wiem czy dobrze to opisa&#322;em.&lt;/p&gt;


	&lt;p&gt;Oczywi&#347;cie mo&#380;na to rozwi&#261;za&#263; &#322;&#261;cz&#261;c komenetarze.py z uzytkownicy.py ale je&#380;eli struktura jest skomplikowana i opis u&#380;ytkownika sk&#322;ada si&#281; np. z 10 tabel a komentarze chce si&#281; mie&#263; odseparowane i przeno&#347;ne to ju&#380; nie jest halo.&lt;/p&gt;


	&lt;p&gt;Nie mia&#322;em ostatnio czasu si&#281; zastanowi&#263;  nad tym problemem ale zapewne do nie go wr&#243;c&#281;.&lt;/p&gt;</description>
      <pubDate>Sun, 16 Dec 2007 19:46:23 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:a9862b41-5f69-4447-8d50-ff76a1b80c0f</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1297</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by climbus</title>
      <description>&lt;p&gt;from pylons_app.lib.base import *&lt;/p&gt;


	&lt;p&gt;Czy model i Session nie jest wci&#261;gany poprzez lib.base? Przynajmniej do 0.9.5 tak by&#322;o.&lt;/p&gt;


	&lt;p&gt;Shell ma defaultowo zaimportowane &#347;rdowisko z lib base + kilka innych zmiennych jak mapper, app.&lt;/p&gt;</description>
      <pubDate>Sun, 16 Dec 2007 19:34:25 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:418da696-466a-4700-90f8-58be96e91ba7</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1296</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;Z tym Mako to chcia&#322;em podkre&#347;li&#263; &#380;e pracuje na natywnych obiektach unikodowych Pythona, a nie na stringach takich czy siakich (cho&#263;by i utf8). Z tym rodzieleniem modelu i b&#322;&#281;dem importu to nie za bardzo wiem w czym  problem.&lt;/p&gt;


	&lt;p&gt;BTW, wrzuci&#322;em na serwer &lt;a href="http://blog.zabiello.com/files/szybki-start.zip" rel="nofollow"&gt;pliki &#378;r&#243;d&#322;owe&lt;/a&gt; z opisywanymi przyk&#322;adami.&lt;/p&gt;</description>
      <pubDate>Sun, 16 Dec 2007 15:42:20 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:9e60fb4f-8326-4167-ac23-bed7e3023421</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1295</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by Tomasz Nazar</title>
      <description>&lt;p&gt;Co do SQLAlchemy, to jest potezne. W porownaniu z Hibernate, mam mieszane uczucia. Hibernate, ma mnostwo dokumentacji i jest dobrze zorganizowane (no i ma 2nd level cache za darmo).
Natomiast w SQLAlchemy, to czesto jeszcze sie gubie.&lt;/p&gt;


	&lt;p&gt;Uwaga co do Mako vs. Utf8 zbedna. Wyjscie mozna ustawic na utf8.&lt;/p&gt;


	&lt;p&gt;PS. A moze wiesz jak rozdzielic klasy modelu w Pylons na osobne pliki. Juz mialem kilka podejsc i ciagle koncze na bledzie rekursywnego importu :(&lt;/p&gt;</description>
      <pubDate>Sun, 16 Dec 2007 14:08:58 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:eba690ec-9c8d-48e6-8aa4-cb558c5ee938</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1294</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by fan</title>
      <description>&lt;p&gt;Jarku artyku&#322; jak zawsze full pro, m&#243;g&#322; by&#347; poruszy&#263; jeszcze w kt&#243;rym&#347; z najbli&#380;szych artyku&#322;&#243;w jak u&#380;y&#263; w merbie cho&#263;by plugina restful_authentication? My&#347;le, &#380;e jeden konkretny artykulik rozwia&#322; by pytanie czy truudno przemigrowa&#263; sw&#243;j projekt na merba, a wyra&#378;nie wida&#263; , &#380;e w sieci o nim coraz g&#322;o&#347;niej.&lt;/p&gt;</description>
      <pubDate>Sun, 16 Dec 2007 12:32:53 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:7a36e3c2-9c26-4363-ad6e-d84e4f2ffee8</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1292</link>
    </item>
    <item>
      <title>"Szybki start z Rails, Merb i Pylons" by comboy</title>
      <description>&lt;p&gt;Bardzo fajny artyku&#322;, dzi&#281;ki :)&lt;/p&gt;</description>
      <pubDate>Sun, 16 Dec 2007 11:45:16 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:a420ecb3-9c49-4c0e-8596-31b69c53fa31</guid>
      <link>http://blog.zabiello.com/articles/2007/12/16/howto-rails-merb-pylons#comment-1290</link>
    </item>
  </channel>
</rss>
