<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Jaros&#322;aw Zabie&#322;&#322;o - BLOG: Tag sqlalchemy</title>
    <link>http://blog.zabiello.com/articles/tag/sqlalchemy</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>SQLAlchemy - pythonowy ORM</title>
      <description>&lt;p&gt;U&#380;ytkownicy Rails&#243;w maj&#261; u&#322;atwione zadanie z u&#380;yciem baz danych. Maj&#261; sw&#243;j &lt;a href="http://api.rubyonrails.org/files/vendor/rails/activerecord/README.html"&gt;Active Record&lt;/a&gt;, &#322;adny i czytelny &lt;a href="http://en.wikipedia.org/wiki/Object-relational_mapping"&gt;&lt;span class="caps"&gt;ORM&lt;/span&gt;&lt;/a&gt;. Mo&#380;e nie posiada on ani szybko&#347;ci ani mo&#380;liwo&#347;ci  takich jak pythonowy &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;, ale jest wzgl&#281;dnie elegancki&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; i prosty do nauki.&lt;/p&gt;


	&lt;p&gt;W &#347;wiecie &lt;span class="caps"&gt;ORM&lt;/span&gt;&amp;#8217;&#243;w Pythona do niedawna kr&#243;lowa&#322; &lt;a href="http://www.sqlobject.org/"&gt;SQLObject&lt;/a&gt; ale jest bardzo mocno wypierany przez znacznie pot&#281;&#380;niejszy &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;. Niestet, SA nie jest specjalnie &#322;atwy do opanowania. Szczeg&#243;lnie m&#281;tne s&#261; r&#243;&#380;ne opisy rozpocz&#281;cia pracy z SA. Preferownych jest wiele styli, zupe&#322;nie wbrew pythonowemu paradygmatowi o jednej, zalecanej drodze post&#281;powania. Jest te&#380; modu&#322; &lt;span class="caps"&gt;WSGI&lt;/span&gt; &lt;a href="http://cheeseshop.python.org/pypi/Alchemyware"&gt;Alchemyware&lt;/a&gt; kt&#243;ra dzia&#322;a w miar&#281; dobrze z jednym wyj&#261;tkiem &amp;#8211; &lt;a href="http://paste.lisp.org/display/36605"&gt;&#378;le dzia&#322;a z baz&#261; &lt;span class="caps"&gt;MSSQL&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;Elixir (SQLAlchemy + sk&#322;adnia Active Record)&lt;/h3&gt;


	&lt;p&gt;Biblioteka &lt;a href="http://elixir.ematia.de/index.html"&gt;Elixir&lt;/a&gt; ma szans&#281; sta&#263; si&#281; hitem dla Pythona, bo jest wrapperem na mocny &lt;span class="caps"&gt;ORM&lt;/span&gt; jakim jest SQLAlchemy. Elixir udost&#281;pnia &lt;a href="http://elixir.ematia.de/examples.html"&gt;bardzo &#322;adn&#261; sk&#322;adni&#281;&lt;/a&gt; wzorowan&#261; na railsowym Active Record.&lt;/p&gt;


	&lt;h3&gt;Migrate (SQLAlchemy + migracje)&lt;/h3&gt;


	&lt;p&gt;SQLAlchemy doczeka&#322;o si&#281; te&#380; projektu implementuj&#261;cego wersjonowanie struktury bazy &amp;#8211; &lt;a href="http://erosson.com/migrate/trac/"&gt;Migrate&lt;/a&gt;&lt;/p&gt;


&lt;hr align="left" width="30%" size="1" /&gt;

	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Mo&#380;na czepia&#263; si&#281; sk&#322;adni :conditions =&amp;gt; &amp;#8220;kt&#243;ra wymaga klepania &lt;span class="caps"&gt;SQL&lt;/span&gt;&amp;#8217;a&amp;#8221;, ale to mo&#380;na poprawi&#263; za pomoc&#261; pluginu &lt;a href="http://brainspl.at/articles/2006/06/30/new-release-of-ez_where-plugin"&gt;ez_where&lt;/a&gt;. Szkoda &#380;e to nie jest standardowo dodane do Active Record.&lt;/p&gt;</description>
      <pubDate>Wed, 14 Feb 2007 01:31:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:24512e85-01fd-477a-9917-5815287347dd</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2007/02/14/sqlalchemy</link>
      <category>python</category>
      <category>sqlalchemy</category>
    </item>
    <item>
      <title>Pylons 0.9.4</title>
      <description>&lt;p&gt;Wysz&#322;a nowa wersja pythonowego megaframeworka (korzysta z zewn., ju&#380; istniej&#261;cych bibliotek) do szybkiego budowania aplikacji webowych &amp;#8211; &lt;a href="http://pylonshq.com"&gt;Pylons&lt;/a&gt;. W wersji 0.9.4 &lt;a href="http://groups.google.com/group/pylons-discuss/browse_thread/thread/1f05fee97b1e5217/2147ea572dc235b5?hl=en#2147ea572dc235b5"&gt;dodano troch&#281; poprawek i ulepsze&#324;&lt;/a&gt;. M.in. jest nowy &lt;a href="http://routes.groovie.org/"&gt;Routes&lt;/a&gt; 1.6.1, ulepszono introspekcj&#281; dla &lt;span class="caps"&gt;XML&lt;/span&gt;-RPC,Akcje kontroler&#243;w s&#261; teraz generatorami a helpery oraz metoda _ (z gettext) generuj&#261; teraz obiekty Unicodowe zamiast string&#243;w &lt;span class="caps"&gt;UTF&lt;/span&gt;-8. Znowu Pylons znacznie wyprzedza, to co dopiero jest w powijakach dla &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;SQLAlchemy&lt;/h3&gt;


	&lt;p&gt;Coraz bardziej zaznacza si&#281; tendencja w u&#380;ywanych pod Pythonem &lt;span class="caps"&gt;ORM&lt;/span&gt;&amp;#8217;ach (Pylons mo&#380;e korzysta&#263; z dowolnych) aby zamiast &lt;a href="http://www.sqlobject.org/"&gt;SQLObject&lt;/a&gt; wybiera&#263; raczej &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;. Ten drugi jest uwa&#380;any za znacznie bardziej wyrafinowany i o wi&#281;kszych mo&#380;liwo&#347;ciach. Na li&#347;cie dyskusyjnej Pylons&#243;w Ben Bangert pokaza&#322; &lt;a href="http://groups.google.com/group/pylons-discuss/browse_thread/thread/1f05fee97b1e5217/2147ea572dc235b5?hl=en#2147ea572dc235b5"&gt;jak w praktyce mo&#380;na u&#380;ywa&#263; SQLAlchemy&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;Szablony&lt;/h3&gt;


	&lt;p&gt;Pylons potrafi korzysta&#263; z dowolnych system&#243;w szablon&#243;w dost&#281;pnych dla 
Pythona. Generalnie, popularne s&#261; dwa podej&#347;cia. Szablony pisane pod propgramist&#243;w lub pod webmaster&#243;w/designer&#243;w, kt&#243;rzy zajmuj&#261; si&#281; sam&#261; kwesti&#261; prezentacji, wizualizacji i pracuj&#261; najcz&#281;&#347;ciej ze &amp;#8220;wspomagaczami&amp;#8221; takimi jak edytor Dreamweaver.&lt;/p&gt;


	&lt;p&gt;Dla tych drugich, polecane jest podej&#347;cie albo takie jak promuje Django, czyli &lt;a href="http://www.djangoproject.com/documentation/templates/"&gt;specjalnie uproszczony j&#281;zyk szablon&#243;w&lt;/a&gt; umo&#380;liwiaj&#261;cym generowanie zar&#243;no &lt;span class="caps"&gt;HTML&lt;/span&gt; jak i &lt;span class="caps"&gt;CSS&lt;/span&gt;, czy innej dowolnej tre&#347;ci.&lt;/p&gt;


	&lt;p&gt;Albo podej&#347;cie jeszcze bardziej uproszczone (dla designer&#243;w, nie dla programist&#243;w), czyli koncepcja, jak&#261; promuj&#261; tw&#243;rcy frameworka &lt;a href="http://zope.org"&gt;Zope&lt;/a&gt;. Chodzi o szablony &lt;a href="http://www.zope.org/Documentation/ZopeBook/ZPT.stx"&gt;&lt;span class="caps"&gt;ZPT&lt;/span&gt;&lt;/a&gt;, &lt;a href="http://kid-templating.org/"&gt;Kid&lt;/a&gt; czy &lt;a href="http://genshi.edgewall.org/"&gt;Genshi&lt;/a&gt; gdzie logika szablon&#243;w jest dodana do atrybut&#243;w. Dzi&#281;ki temu s&#261; one przezroczyste dla edytor&#243;w takich jak Dreamweaver i je&#347;li wymagana jest cz&#281;sta konsultacja z designerami to takie podej&#347;cie oszcz&#281;dza ponownego, r&#281;cznego dodawania logiki dla programist&#243;w.&lt;/p&gt;


	&lt;h3&gt;Nadchodzi Mako&lt;/h3&gt;


	&lt;p&gt;Moim zdaniem, znacznie lepszym podej&#347;ciem jest podej&#347;cie jakie oferuj&#261; szablony &lt;a href="http://www.cheetahtemplate.org/"&gt;Cheetah&lt;/a&gt; czy &lt;a href="http://myghty.org"&gt;Myghty&lt;/a&gt;. Te drugie, s&#261; aktualnie najpote&#380;niejsze. Maj&#261; nie tylko du&#380;a szybko&#347;&#263;, ale bardzo dobrze dzia&#322;aj&#261;cy (lepszy od Cheetah) cache oraz &#322;atwo&#347;&#263; do tworzenia komponent&#243;w, klock&#243;w wielokrotnego u&#380;ycia.&lt;/p&gt;


	&lt;p&gt;Nadchodzi jednak co&#347; jeszcze lepszego. Developerzy Pylons&#243;w szykuj&#261; zupe&#322;nie nowy system szablon&#243;w zwany Mako (&lt;a href="http://makotemplates.org"&gt;http://makotemplates.org&lt;/a&gt;). Jest on wzorowany na najlepszych funkcjach jakie oferuj&#261; Myghty, Cheetah, Genshi i Django. Jest te&#380; bardzo szybki.&lt;/p&gt;


	&lt;p&gt;Mako oferuj&#261; wielostrefowe dziedziczenie (podobnie jak Cheetah i Django). Nie jest te&#380; wymagane tak jak w Myghty, aby wstawki Pythona (zaczynaj&#261;ce si&#281; w szablonach Myghty od znaku procenta) zaczyna&#322;y wiersz. Mo&#380;na wstawia&#263; je w &#347;rodku tekstu lub gdziekolwiek w ramach tag&#243;w &amp;lt;% kod Pythona %&amp;gt;.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;&amp;lt;%&lt;/span&gt;&lt;span class="ident"&gt;inherit&lt;/span&gt; &lt;span class="ident"&gt;file&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;base.html&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;/&amp;gt;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;lt;%&lt;/span&gt;
    &lt;span class="ident"&gt;rows&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[[&lt;/span&gt;&lt;span class="ident"&gt;v&lt;/span&gt; &lt;span class="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;v&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;0&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="keyword"&gt;for&lt;/span&gt; &lt;span class="ident"&gt;row&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;0&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="punct"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="string"&gt;
&amp;lt;table&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&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;row&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;rows&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
        &lt;span class="global"&gt;${&lt;/span&gt;&lt;span class="ident"&gt;makerow&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;row&lt;/span&gt;&lt;span class="punct"&gt;)}&lt;/span&gt;
    &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="ident"&gt;endfor&lt;/span&gt;
&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="regex"&gt;table&amp;gt;

&amp;lt;%def name=&amp;quot;makerow(row)&amp;quot;&amp;gt;
    &amp;lt;tr&amp;gt;
    % for name in row:
        &amp;lt;td&amp;gt;${name}&amp;lt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;td&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;\&lt;/span&gt;
    &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="ident"&gt;endfor&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="regex"&gt;tr&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span class="punct"&gt;/%&lt;/span&gt;&lt;span class="keyword"&gt;def&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Unikalne dziedziczenie dynamiczne (zmienna mo&#380;e okre&#347;la&#263; kt&#243;re szablony maj&#261; by&#263; bazowymi dla innych). Szablony mog&#261; by&#263; te&#380; buforowane. Mo&#380;na wygodnie filtrowa&#263; dane w stylu Django (Python) czy Smarty (PHP).&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;&amp;lt;%!&lt;/span&gt;&lt;span class="string"&gt;
    def myescape(text):
        return &amp;quot;&amp;lt;TAG&amp;gt;&amp;quot; + text + &amp;quot;&amp;lt;/TAG&amp;gt;&amp;quot;
%&amp;gt;

Heres some tagged text: ${&amp;quot;text&amp;quot; | myescape}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Oczywi&#347;cie mo&#380;na dowolny element szablon&#243;w keszowa&#263; na wiele sposob&#243;w.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;&amp;lt;%&lt;/span&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;name=&amp;quot;mycomp&amp;quot;&lt;/span&gt; &lt;span class="ident"&gt;cache&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="ident"&gt;cache_timeout&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;30&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="ident"&gt;cache_type&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;memory&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&amp;gt;&lt;/span&gt;
    &lt;span class="ident"&gt;other&lt;/span&gt; &lt;span class="ident"&gt;text&lt;/span&gt;
&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="regex"&gt;%def&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Pylons 0.9.4 ma ju&#380; wbudowan&#261; obs&#322;ug&#281; dla Mako. Wystarczy je &#347;ci&#261;gn&#261;&#263; z &lt;span class="caps"&gt;SVN&lt;/span&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;svn&lt;/span&gt; &lt;span class="ident"&gt;co&lt;/span&gt; &lt;span class="ident"&gt;http&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;svn&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;makotemplates&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;org&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;mako&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;trunk&lt;/span&gt; &lt;span class="ident"&gt;mako&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Po zainstalowaniu, jedyne co trzeba, to doda&#263; opcj&#281;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;template_engine&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;mako&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;do wywo&#322;ania config.init_app w middleware.py.&lt;/p&gt;</description>
      <pubDate>Sun, 31 Dec 2006 02:40:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:b86334ce-b3bf-4224-9d6f-e02573d3a4a6</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/12/31/pylons-0-9-4</link>
      <category>Pylons</category>
      <category>pylons</category>
      <category>mako</category>
      <category>sqlalchemy</category>
      <category>genshi</category>
    </item>
    <item>
      <title>MySQLdb &amp;amp; client encoding</title>
      <description>&lt;p&gt;[vide: &lt;a href="http://blog.zabiello.com/pages/en/mysqldb-client-encoding"&gt;English version&lt;/a&gt;]&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://sourceforge.net/projects/mysql-python"&gt;MySQLdb&lt;/a&gt; to g&#322;&#243;wna biblioteka dla Pythona obs&#322;uguj&#261;ca baz&#281; MySQL. Baza ta (od werseji 4.1 wzwy&#380;) ma wbudowany wygodny mechanizm translacji znak&#243;w jakie maj&#261; by&#263; wy&#347;wietlane dla klienta. Oczywi&#347;cie, nale&#380;y za&#322;o&#380;y&#263;, &#380;e natywnym formatem danych dla bazy to &lt;span class="caps"&gt;UTF&lt;/span&gt;-8. Za pomoc&#261; prostej kwerendy (SET &lt;span class="caps"&gt;NAMES&lt;/span&gt; latin2) mo&#380;na wymusi&#263; aby wszelkie napisy by&#322;y wypluwane do klienta w wybranym formacie (tu: iso-8859-2).&lt;/p&gt;


	&lt;p&gt;Ostatnio, przy okazji pracy z &lt;a href="http://pylonshq.com"&gt;Pylons&lt;/a&gt;, przyjrza&#322;em si&#281; bardzo ciekawemu projektowi: &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;. Wszystko wskazuje na to, &#380;e &lt;a href="http://www.sqlobject.org/"&gt;SQLObject&lt;/a&gt; odejdzie do lamusa (tym bardziej &#380;e jego tw&#243;rca co&#347; go porzuci&#322; i planuje stworzy&#263; nowy SQLObject2). &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt; jest nie tylko znacznie pote&#380;niejszym &lt;a href="http://en.wikipedia.org/wiki/Object-relationship_modeling"&gt;&lt;span class="caps"&gt;ORM&lt;/span&gt;&lt;/a&gt;, ale ma tak&#380;e znacznie lepsz&#261; dokumentacj&#281; ni&#380; SQLObject &amp;#8211; ok. 117 stron samego tylko &lt;a href="http://www.sqlalchemy.org/docs/"&gt;manuala&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Jedyny problem, jakie to typowe, to brak czytelnej opcji translacji polskich znak&#243;w. Podobny problem swego czasu znalaz&#322;em w Django (wys&#322;a&#322;em patcha i to poprawili dodaj&#261;c na sztywno &amp;#8220;SET &lt;span class="caps"&gt;NAMES&lt;/span&gt; utf8&amp;#8221;) W wypadku SQLAlchemy nie ma opcji do definicji kodowania po stronie klienta. Manual wspomina tylko o ustawieniu kodowania dla bazy, a to nie to samo. Okazuje, si&#281;, &#380;e rozwi&#261;zanie jest bardzo proste. Podczas tworzenia po&#322;&#261;czenia do bazy wystarczy u&#380;y&#263; dodatkowych parametr&#243;w. Nie ma potrzeby bawienia si&#281; w &#380;adne kwerendy &amp;#8220;SET &lt;span class="caps"&gt;NAMES&lt;/span&gt;&amp;#8221;. Owe parametry to &lt;strong&gt;use_unicode&lt;/strong&gt; i &lt;strong&gt;charset&lt;/strong&gt;:&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="constant"&gt;MySQLdb&lt;/span&gt;
&lt;span class="ident"&gt;conn&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;MySQLdb&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;user&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;root&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
    &lt;span class="ident"&gt;passwd&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
    &lt;span class="ident"&gt;db&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
    &lt;span class="ident"&gt;use_unicode&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;False&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; 
    &lt;span class="ident"&gt;charset&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;cp1250&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W powy&#380;szym wypadku, MySQL b&#281;dzie zak&#322;ada&#322; &#380;e klient ma odebra&#263; teksty w formacie string&#243;w cp1250. Za&#347; w wypadku u&#380;ycia &amp;#8220;use_unicode=True&amp;#8221; zwracane b&#281;d&#261; &#347;liczne obiekty unicodowe! Przyk&#322;adowy plik konfiguracyjny dla Pylonsa korzystaj&#261;cego z SQLAlchemy (config/&lt;i&gt;init&lt;/i&gt;.py) mo&#380;e zatem wygl&#261;da&#263; np. tak:&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;sqlalchemy&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;import&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&lt;/span&gt; &lt;span class="ident"&gt;as&lt;/span&gt; &lt;span class="ident"&gt;pool&lt;/span&gt;
&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;MySQLdb&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;getconn&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;MySQLdb&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;user&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;root&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
        &lt;span class="ident"&gt;passwd&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
        &lt;span class="ident"&gt;db&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
        &lt;span class="ident"&gt;use_unicode&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;False&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; 
        &lt;span class="ident"&gt;charset&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;utf8&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;

&lt;span class="ident"&gt;db&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;create_engine&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;mysql://root:@localhost/test&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
    &lt;span class="ident"&gt;pool&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;pool&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;QueuePool&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;getconn&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;pool_size&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;20&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;max_overflow&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;40&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; 
    &lt;span class="ident"&gt;strategy&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;threadlocal&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;BoundMetaData&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;db&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;test_table&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;test&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="ident"&gt;autoload&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="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Test(object):&lt;/span&gt;  
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;__str__&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="keyword"&gt;return&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;title&lt;/span&gt;  

&lt;span class="ident"&gt;test_mapper&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;Test&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;test_table&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W powy&#380;szym przyk&#322;adzie, wymusi&#322;em kodowanie utf8 dla klienta oraz po&#322;&#261;czenie z baz&#261; dzia&#322;a&#263; b&#281;dzie w puli 20-40 w&#261;tk&#243;w. W&#322;a&#347;nie tego mi brakuje w Django: pracy wielow&#261;tkowej, bo zu&#380;ywa ona mniej pami&#281;ci. W/w model mo&#380;na u&#380;y&#263; w kontrolerze Pylons (controllers/home.py) np. tak:&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;myproject&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;from&lt;/span&gt; &lt;span class="ident"&gt;myproject&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;models&lt;/span&gt; &lt;span class="ident"&gt;import&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;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;c&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;rows&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;select&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="ident"&gt;test_table&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;id&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;test_table&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;name&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="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;render_response&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;/home.myt&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Wed, 16 Aug 2006 01:28:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:a7940b1d-4893-4e0a-b1aa-60d91a5a1207</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/08/16/mysqldb-client-encoding</link>
      <category>Databases</category>
      <category>Pylons</category>
      <category>Python</category>
      <category>mysql</category>
      <category>pylons</category>
      <category>python</category>
      <category>sqlalchemy</category>
    </item>
  </channel>
</rss>
