<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>datamapper &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/datamapper/</link>
	<description>Feed of posts on WordPress.com tagged "datamapper"</description>
	<pubDate>Wed, 30 Dec 2009 09:26:07 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Ronin "big-push" 0.3.0 released]]></title>
<link>http://houseofpostmodern.wordpress.com/2009/10/20/ronin-big-push-0-3-0-released/</link>
<pubDate>Tue, 20 Oct 2009 09:19:24 +0000</pubDate>
<dc:creator>postmodern3</dc:creator>
<guid>http://houseofpostmodern.wordpress.com/2009/10/20/ronin-big-push-0-3-0-released/</guid>
<description><![CDATA[The long wait is over. Ronin 0.3.0, code-named &#8220;big-push&#8221;, has finally been released. Da]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>The long wait is over. <a href="http://ronin.rubyforge.org/">Ronin</a> 0.3.0, code-named &#8220;big-push&#8221;, has finally been released.</p>
<h2>DataMapper 0.10.0</h2>
<p>Ronin was probably one of the first big Ruby apps to upgrade to <a href="http://datamapper.org/">DataMapper</a> 0.10.0. As a result of this, we had to postpone the release of Ronin 0.3.0, until DataMapper 0.10.0 had finished it&#8217;s rigorous two month Q/A cycle.</p>
<p>Once DataMapper 0.10.0 had been released, the two months of Q/A and almost a complete rewrite of the code-base really showed itself. I think <a href="http://twitter.com/dkubb">@dkubb</a>, <a href="http://twitter.com/dbussink">@dbussink</a>, <a href="http://sick.snusnu.info/">@snusnu</a>, <a href="http://twitter.com/xshay">@xshay</a>, <a href="http://twitter.com/myabc">@myabc</a>, <a href="http://twitter.com/rsim">@rsim</a>, <a href="http://twitter.com/namelessjon">@namelessjon</a>, <a href="http://twitter.com/knowtheory">@knowtheory</a> and everyone else who helped with 0.10.0 deserves applause for their hard work and dedication.</p>
<h2>YARD</h2>
<p>As of 0.3.0, Ronin has successfully moved to <a href="http://yard.soen.ca/">YARD</a> based documentation. The new Ronin API docs can be found in the usual <a href="http://ronin.rubyforge.org/docs/ronin/">location</a>. YARD really helped improve the detail of the Ronin API docs, allowing developers to specify method arguments, accepted object-types, yield arguments, possible exceptions and return-types.</p>
<p>Additionally, YARD handlers were added to Ronin that parsed and regenerated documentation for DataMapper properties/relations. These additional YARD handlers helped improve documentation coverage for Ronin models, such as <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/Arch.html">Ronin::Arch</a> or <a href="http://ronin.rubyforge.org/docs/ronin-exploits/Ronin/Exploits/Exploit.html">Ronin::Exploits::Exploit</a>.</p>
<h2>Ronin::UI::CommandLine</h2>
<p><kbd>Ronin::UI::CommandLine</kbd> was almost entirely refactored in 0.3.0. <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/CommandLine/Command.html">Ronin::UI::CommandLine::Command</a> was rewritten to use <a href="http://yehudakatz.com/2008/05/12/by-thors-hammer/">Thor</a>. Switching to Thor greatly simplified the ronin commands, making it easier to write new commands. A good example of this, is the source-code for the <kbd>install</kbd> command from <a href="http://github.com/postmodern/ronin/blob/0.2.4/lib/ronin/ui/command_line/commands/install.rb#L31">before</a> and <a href="http://github.com/postmodern/ronin/blob/0.3.0/lib/ronin/ui/command_line/commands/install.rb#L28">after</a> 0.3.0.</p>
<p>Another benefit to using Thor, albeit cosmetic, was being able to use Thor&#8217;s ANSI color-output. Normal output will now appear in green, warnings in yellow and error messages in red.</p>
<p>New convenience methods were also added to <kbd>Ronin::UI::CommandLine::Command</kbd> to help format and print various data: <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/CommandLine/Command.html#indent-instance_method">indent</a>, <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/CommandLine/Command.html#print_title-instance_method">print_title</a>, <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/CommandLine/Command.html#print_array-instance_method">print_array</a> and <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/CommandLine/Command.html#print_hash-instance_method">print_hash</a>.</p>
<h2>Ronin::UI::Output</h2>
<p>As of 0.3.0, <kbd>Ronin::UI::Diagnostics</kbd> and <kbd>Ronin::UI::Verbose</kbd> were replaced with the brand new <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/Output.html">Ronin::UI::Output</a> module. <kbd>Ronin::UI::Output</kbd> is designed to delegate how output is handled. By default all output is sent to <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/Output/Handler.html">Ronin::UI::Output::Handler</a>, which prints the output to the terminal. One can override the default output handler by using <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/Output.html#handler%3D-class_method">Ronin::UI::Output.handler=</a>, to specify the new handler module; which must define <kbd>print_info</kbd>, <kbd>print_debug</kbd>, <kbd>print_warning</kbd> and <kbd>print_error</kbd> methods.</p>
<p><kbd>Ronin::UI::Output</kbd> also provides the <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/Output/Helpers.html">Helpers</a> module, which can be included into any class and adds the <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/Output/Helpers.html#print_info-instance_method">print_info</a>, <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/Output/Helpers.html#print_debug-instance_method">print_debug</a>, <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/Output/Helpers.html#print_warning-instance_method">print_warning</a> and <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/UI/Output/Helpers.html#print_error-instance_method">print_error</a> methods.</p>
<h2>New Convenience Methods</h2>
<p>New TCP and UDP networking methods were added to 0.3.0. Now one can easily create TCP/UDP servers using, <a href="http://ronin.rubyforge.org/docs/ronin/Net.html#tcp_server-class_method">Net.tcp_server</a>, <a href="http://ronin.rubyforge.org/docs/ronin/Net.html#tcp_server_session-class_method">Net.tcp_server_session</a>, <a href="http://ronin.rubyforge.org/docs/ronin/Net.html#tcp_single_server-class_method">Net.tcp_single_server</a>, <a href="http://ronin.rubyforge.org/docs/ronin/Net.html#udp_server-class_method">Net.udp_server</a> and <a href="http://ronin.rubyforge.org/docs/ronin/Net.html#udp_server_session-class_method">Net.udp_server_session</a>.</p>
<p><a href="http://ronin.rubyforge.org/docs/ronin/Ronin/Network/HTTP/Proxy.html">Ronin::Network::HTTP::Proxy</a> was also added to 0.3.0. The <kbd>Ronin::Network::HTTP::Proxy</a> helps parse and represent HTTP proxy addresses, and is now used by <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/Network/HTTP.html#proxy-class_method">Ronin::Network::HTTP.proxy</a> and all <kbd>:proxy</kbd> options.</p>
<pre>proxy = Network::HTTP::Proxy.parse('148.233.239.24:80')
# =&#62; #&#60;Ronin::Network::HTTP::Proxy: 148.233.239.24:80&#62;</pre>
<p>The <kbd>Proxy</kbd> class can also be used to test a proxy.</p>
<pre>proxy.valid?
# =&#62; true
proxy.lag
# =&#62; 0.003881</pre>
<h2>Ronin::Platform</h2>
<p>The <a href="http://github.com/postmodern/ronin/blob/0.3.0/static/ronin/platform/overlay.xsl">overlay.xsl</a> file got a make-over in 0.3.0. <kbd>overlay.xsl</kbd> is a XML StyleSheet, which helps render <a href="http://github.com/postmodern/postmodern-overlay/raw/master/ronin.xml">ronin.xml</a> files from Overlays into proper XHTML when they are viewed in a web-browser. Now <kbd>ronin.xml</kbd> files should appear more like a standard "About" web-page.</p>
<p>Reloading Overlays/Extensions while ronin is running became possible with the addition of <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/Platform.html#reload%21-class_method">Ronin::Platform.reload!</a>. Now if an Extension is modified, one can simply call <kbd>Platform.reload!</kbd> and get the updated version.</p>
<p>Ronin Extensions gained convenience methods for defining reader/writer methods to instance variables: <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/Platform/Extension.html#attr_reader-instance_method">attr_reader</a>, <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/Platform/Extension.html#attr_writer-instance_method">attr_writer</a> and <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/Platform/Extension.html#attr_accessor-instance_method">attr_accessor</a>. They can be used in Ronin Extensions, just as one would use them in a class.</p>
<pre>ronin_extension do

  attr_accessor :var
  attr_reader :result

  setup do
    @var = 5
    @result = nil
  end
  ...
end</pre>
<p>Ronin Extensions also gained their own on-demand temp directory. When <a href="http://ronin.rubyforge.org/docs/ronin/Ronin/Platform/Extension.html#tmp_dir-instance_method">Ronin::Platform::Extension#tmp_dir</a> is called, a temp directory specifically for the extension will be created within <kbd>~/.ronin/tmp/</kbd>, and the path of the new temp directory will be returned.</p>
<h2>Upgrading</h2>
<p>As always, the rubygem files for Ronin 0.3.0 are available on <a href="http://rubyforge.org/frs/?group_id=3798">rubyforge.org</a>. One can update Ronin using rubygems by simplying running:</p>
<pre>$ gem update ronin</pre>
<p>Likewise, one can also install Ronin using rubygems:</p>
<pre>$ gem install ronin</pre>
<p>Also, as of Ronin 0.3.0 all releases of Ronin will also be made available on <a href="http://gemcutter.org/">gemcutter.org</a>.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[DataMapper versus ActiveRecord]]></title>
<link>http://mauricioszabo.wordpress.com/2009/10/06/datamapper-versus-activerecord/</link>
<pubDate>Tue, 06 Oct 2009 14:00:17 +0000</pubDate>
<dc:creator>Maurício Szabo</dc:creator>
<guid>http://mauricioszabo.wordpress.com/2009/10/06/datamapper-versus-activerecord/</guid>
<description><![CDATA[Outro dia, tive um problema chatíssimo com o ActiveRecord: eu precisava criar um código de autentici]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Outro dia, tive um problema chatíssimo com o ActiveRecord: eu precisava criar um código de autenticidade, que conteria várias matrículas, que conteria várias disciplinas. O problema é o seguinte: Essas matrículas só seriam válidas se, por exemplo, o total de créditos das disciplinas não ultrapassassem um determinado número. Logo, resolvi fazer a validação no modelo de autenticidade, da seguinte forma:</p>
<pre class="brush: ruby;">
class Autenticidade &#60; ActiveRecord::Base
  MAX_CREDITOS = 40
  has_many :matriculas
  has_many :disciplinas, :through =&#62; :matriculas
  validate :credito_alto?

  def credito_alto?
    total = disciplinas.inject(0) { &#124;r, v&#124; r += v.creditos }
    errors.add(:disciplinas, 'créditos acima do permitido') if total &#62; MAX_CREDITOS
  end
end

class Matricula &#60; ActiveRecord::Base
  belongs_to :disciplina
  belongs_to :autenticidade
end

class Disciplina &#60; ActiveRecord::Base
end
</pre>
<p>Ok, o problema agora é o seguinte: Se eu crio uma autenticidade, com o parâmetro :disciplina_ids =&#62; [1, 2], por exemplo, e a autenticidade<strong> não é</strong> válida, nenhuma nova matrícula é criada &#8211; como deveria ser. Agora, se eu atualizo uma autenticidade, com o  autenticidade.update_attributes( :disciplina_ids =&#62; [1, 2]), e essa autenticidade não é válida, o ActiveRecord <strong>salva</strong> as matrículas. Nesse caso, eu tenho uma inconsistência na base de dados feia &#8211; e precisava encontrar uma alternativa que não envolvesse muitos hacks, coisa que ainda não encontrei. Mas isso me estimulou a pesquisar o DataMapper.</p>
<p><!--more--></p>
<p>O <a href="http://datamapper.org/" target="_blank">DataMapper</a> é um ORM assim como o ActiveRecord &#8211; porém com um diferencial que (para alguns) é interessante: Ele só lança os comandos SQL quando você precisa. Nossa autenticidade (fora as validações) ficaria assim:</p>
<pre class="brush: ruby;">
class Autenticidade
  include DataMapper::Resource

  MAX_CREDITOS = 40
  property :id, Serial
  property :codigo_autenticidade, String
  has n, :matriculas
  has n, :disciplinas, :through =&#62; :matriculas
end
</pre>
<p>Para alguns, é uma vantagem declarar as propriedades no próprio código &#8211; dizem que é mais simples de ver o que há nas suas tabelas. Eu, discordo categoricamente disso &#8211; o código-fonte não deveria fazer o que a documentação faz (se você não tem um dicionário de dados, é culpa sua, não do ActiveRecord). Mas uma coisa legal é: Se vc fizer, por exemplo: <strong>a = Autenticidade.all[0]</strong>, o DataMapper gera apenas o SQL que você precisaria (nesse caso, <strong>SELECT * FROM autenticidades LIMIT 1</strong>). Isso funciona, de acordo com a documenação do DataMapper, inclusive para relações:</p>
<pre class="brush: ruby;">
autenticidades = Autenticidade.all #Não gera nenhum SQL ainda
autenticidades.each do &#124;autenticidade&#124; #Gera um SELECT * FROM autenticidades
  p autenticidade.matriculas #Gera um SELECT para listar TODAS as matrículas de TODAS as autenticidades, apenas na primeira iteração
end
</pre>
<p>Ok, isso elimina o tal do problema n+1 (No ActiveRecord, isso geraria um SELECT para cada autenticidade). O problema é: isso funciona muito bem, mas no <strong>has n, :through</strong>, o problema do n+1 existe! E, para piorar, um <strong>Autenticidade.all :include =&#62; :disciplinas</strong> simplesmente não existe, logo eu não tenho como sair desse erro. No fim, a vantagem virou uma desvantagem.</p>
<p>Outra vantagem que eu tinha visto era a possibilidade de criar adaptadores para coisas que não são bases de dados relacionais &#8211; imagine, por exemplo, você usando o DataMapper como um ORM para LDAP, MySQL, REST e YAML, tudo ao mesmo tempo &#8211; fazer associações com isso seria uma maravilha, falar que seu usuário do MySQL tem uma entrada LDAP, usando as associações do próprio DataMapper. Porém, mais uma vez, as coisas não funcionaram muito bem: <strong>has n</strong> só funciona quando as bases de dados estão no mesmo adaptador, talvez para otimizar os SQLs com JOINs, etc. Logo, mais uma vantagem que eu vi foi sub-utilizada.</p>
<p>No fim, a única vantagem que o DataMapper me deu foi a possibilidade de fazer isso aqui:</p>
<pre class="brush: ruby;">
autenticidade = Autenticidade.first
autenticidade.disciplinas &#60;&#60; Disciplina.get(:id =&#62; 1)
autenticidade.disciplinas &#60;&#60; Disciplina.get(:id =&#62; 2)
autenticidade.save #Se for falso, NÃO salva as disciplinas
</pre>
<p>Pois é, eu gostaria mais de ver as vantagens do DataMapper no ActiveRecord do que o inverso&#8230;</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Initial version of DataMapper Oracle adapter]]></title>
<link>http://blog.rayapps.com/2009/07/21/initial-version-of-datamapper-oracle-adapter/</link>
<pubDate>Tue, 21 Jul 2009 16:52:34 +0000</pubDate>
<dc:creator>Raimonds Simanovskis</dc:creator>
<guid>http://blog.rayapps.com/2009/07/21/initial-version-of-datamapper-oracle-adapter/</guid>
<description><![CDATA[What is DataMapper? DataMapper is Ruby Object/Relational Mapper that is similar to ActiveRecord (com]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><img src="http://rayapps.files.wordpress.com/2009/07/datamapper.jpg?w=347&#038;h=91" alt="datamapper.jpg" border="0" width="347" height="91" align="right" style="padding:0 4px 4px 8px;" /></p>
<h3>What is DataMapper?</h3>
<p><a href="http://www.datamapper.org">DataMapper</a> is Ruby Object/Relational Mapper that is similar to ActiveRecord (component of <a href="http://rubyonrails.org/">Ruby on Rails</a>) but still it handles several things differently than ActiveRecord.</p>
<p>I got interested in DataMapper because I liked better some of its design decisions when compared with ActiveRecord. And in particular DataMapper architecture can suite better if you need to work with legacy Oracle database schemas &#8211; that is the area where I use Ruby on Rails a lot and for these purposes I also created <a href="http://github.com/rsim/oracle-enhanced">Oracle enhanced adapter for ActiveRecord</a>.</p>
<p>But as there were no Oracle adapter available for DataMapper I needed to create one <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I started to work on Oracle adapter for DataMapper after the RailsConf and now it is passing all DataMapper tests on all Ruby platforms &#8211; MRI 1.8, Ruby 1.9 and JRuby 1.3.</p>
<h3>Why DataMapper for Oracle database?</h3>
<p>If you would like to learn main differences between DataMapper and ActiveRecord then please start with <a href="http://www.datamapper.org/doku.php?id=getting_started_with_datamapper">this overview</a> and <a href="http://www.datamapper.org/doku.php?id=why_datamapper">this summary of benefits</a>.</p>
<p>Here I will mention specific benefits if you would like to use DataMapper with Oracle database.</p>
<h4>Model properties</h4>
<p>In DataMapper you always specify in model class definition what Ruby &#8220;type&#8221; you would like to use for each model attribute (or property as called in DataMapper):</p>
<pre>
class Post
  include DataMapper::Resource
  property :id,         Serial
  property :title,      String
  property :post_date,  Date
  property :created_at, DateTime
  property :updated_at, Time
end
</pre>
<p>The main benefit for that is that you can explicitly define when to use Ruby Time, Date or DateTime class which is stored as DATE (or sometimes as TIMESTAMP) in Oracle database. In addition you can define your own custom DataMapper types and define how to serialize them into database.</p>
<h4>Composite primary keys</h4>
<p>DataMapper core library supports composite primary keys for models. If you use ActiveRecord then there is an option to use additional composite_primary_keys gem but it regularly breaks with latest ActiveRecord versions and quite often it also might break in some edge cases. In DataMapper composite primary keys are defined quite simple:</p>
<pre>
class City
  include DataMapper::Resource
  property :country,   String, :key =&#62; true
  property :name,      String, :key =&#62; true
end
</pre>
<h4>Legacy schemas</h4>
<p>DataMapper is quite useful when you want to put Ruby models on top of existing Oracle schemas. It is possible to provide different database field name for property or provide custom sequence name for primary keys:</p>
<pre>
class Post
  include DataMapper::Resource
  property :id, Serial, :field =&#62; "post_id", :sequence =&#62; "post_s"
end
</pre>
<p>You can also define one model that can be persisted in two different repositories (e.g. databases or schemas) and use different naming conventions in each repository:</p>
<pre>
class Post
  include DataMapper::Resource
  repository(:old) do
    property :id, Serial, :field =&#62; "post_id", :sequence =&#62; "post_s"
  end
  repository(:default) do
    property :id, Serial
  end
end
</pre>
<p>As a result DataMapper can be used also for data migration between different databases.</p>
<h4>Bind variables</h4>
<p>ActiveRecord always generates SQL statements for execution as one single string. Therefore Oracle enhanced adapter always initializes Oracle session with setting cursor_sharing=&#8217;similar&#8217;. It instructs Oracle always to take all literals (constants) from SQL statement and replace them with bind variables. It reduces the number of unique SQL statements generated but also it is some overhead for Oracle optimizer.</p>
<p>DataMapper always passes all statement parameters separately to corresponding database adapter and therefore it is possible for Oracle adapter to pass all parameters as bind variables to Oracle.</p>
<h4>CLOB and BLOB values inserting and selecting</h4>
<p>As for ActiveRecord all inserted values should be passed as literals in INSERT statement it was not possible to insert large CLOB and BLOB values directly in INSERT statement. Therefore ActiveRecord Oracle enhanced adapter did separate call-backs for inserting any CLOB or BLOB data after INSERT of other data. In DataMapper it is possible to insert all data at once as CLOB and BLOB data are passed as bind variables.</p>
<p>DataMapper also handles better lazy loading of large columns. So if you define property as Text then by default it will not be selected from database &#8211; it will be selected separately only when you use it. Typically it could reduce amount of data that needs to be sent from database to application as Text properties are quite often not needed in e.g. all web pages.</p>
<h4>Wny not DataMapper?</h4>
<p>If you are fine with ActiveRecord default conventions and you don&#8217;t have any issues that I listed previously then probably ActiveRecord is good enough for you and you shouldn&#8217;t change to DataMapper. There are of course much more Rails plugins that work with ActiveRecord but not yet with DataMapper. And DataMapper is still much less used and therefore there might some edge cases where it is not tested and you will need to find the issue causes by yourself.</p>
<p>But if you like to try new things then please try it out &#8211; and also DataMapper community is quite friendly and helpful and will help to solve any issues <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Installation of DataMapper Oracle adapter</h3>
<p>So if you have decided to try to use DataMapper with Oracle database then follow the instructions how to install it.</p>
<p>Oracle support is done for current development version 0.10.0 of DataMapper &#8211; therefore you will need to install the latest versions from GitHub (they are still not published as gems on RubyForge).</p>
<p>DataMapper with Oracle adapter can be used both on MRI 1.8.6 (I am not testing it on 1.8.7) and Ruby 1.9.1 as well as on JRuby 1.3. And currently installation is tested on Mac OS X and Linux &#8211; if there is anyone interested in Windows support then please let me know.</p>
<h4>MRI 1.8.6 or Ruby 1.9.1</h4>
<p>At first you need to have the same preconditions as for ActiveRecord:</p>
<ul>
<li>Oracle Instant Cient</li>
<li>ruby-oci8 gem, version 2.0.2 or later</li>
</ul>
<p>If you are using Mac then you can use <a href="http://blog.rayapps.com/2008/04/24/how-to-setup-ruby-and-new-oracle-instant-client-on-leopard/">these instructions</a> for installation (but instead of compiling ruby-oci8 library just install ruby-oci8 gem).</p>
<p>Now at first it is necessary to install DataObjects Oracle driver &#8211; DataObjects library is unified interface to relational databases (like SQLite, MySQL, PostgreSQL, Oracle) that DataMapper uses to access these databases.</p>
<p>At first validate that you have the latest version of rubygems installed and install necessary additional gems:</p>
<pre>
gem update --system
gem install addressable -v 2.0
</pre>
<p>As I mentioned currently you need to install the latest version from GitHub (at first create and go to directory where you would like to store DataMapper sources):</p>
<pre>
git clone git://github.com/datamapper/extlib.git
cd extlib
git checkout -b next --track origin/next
rake install
cd ..
</pre>
<pre>
git clone git://github.com/datamapper/do.git
cd do
git checkout -b next --track origin/next
cd data_objects
rake install
cd ../do_oracle
rake compile
rake install
cd ../..
</pre>
<p>Now if DataObjects installation was successful you can install DataMapper. UPDATE: Oracle adapter is now in &#8220;next&#8221; branch of DataMapper so now you need to install it form there:</p>
<pre>
git clone git://github.com/datamapper/dm-core.git
cd dm-core
git checkout -b next --track origin/next
rake install
</pre>
<p>Now start irb and test if you can connect to Oracle database (change database name, username and password according to your setup):</p>
<pre>
require "rubygems"
require "dm-core"
DataMapper.setup :default, "oracle://hr:hr@xe"
</pre>
<p>and try some basic DataMapper operations (I assume that you don&#8217;t have posts table in this schema):</p>
<pre>
class Post
  include DataMapper::Resource
  property :id,     Serial, :sequence =&#62; "posts_seq"
  property :title,  String
end
DataMapper.auto_migrate!
p = Post.create(:title=&#62;"Title")
Post.get(p.id)
Post.auto_migrate_down!
</pre>
<h4>JRuby</h4>
<p>At first I assume that you have already installed JRuby latest version (1.3.1 at the moment).</p>
<p>Then you need to place Oracle JDBC driver ojdbc14.jar file in JRUBY_HOME/lib directory (other option is just to put somewhere in PATH).</p>
<p>All other installation should be done in the same way &#8211; just use &#8220;jruby -S gem&#8221; instead of &#8220;gem&#8221; and &#8220;jruby -S rake&#8221; instead of &#8220;rake&#8221; and it should install necessary gems for JRuby.</p>
<p>In addition before installing do_oracle gem you need to install do_jdbc gem (which contains general JDBC driver functionality):</p>
<pre>
# after installation of data_objects gem
cd ../do_jdbc
jruby -S rake compile
jruby -S rake install
# continue with do_oracle installation
</pre>
<h4>Other DataMapper gems</h4>
<p>DataMapper is much more componentized than ActiveRecord. Here I described how to install just the main dm-core gem. You can see the list of <a href="http://www.datamapper.org/doku.php?id=gem_maintainers">other gems in DataMapper web site</a>.</p>
<p>To install additional DataMapper gems you need to</p>
<pre>
git clone git://github.com/datamapper/dm-more.git
cd dm-more
git checkout -b next --track origin/next
cd dm-some-other-gem
rake install
</pre>
<h3>Questions?</h3>
<p>This was my first attempt to describe how to start to use DataMapper with Oracle. If you have any questions or something is not working for you then please write comments and I will try to answer and fix any issues in these instructions.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[My aproach for doing "DDD on Ruby" - Introduction and Part I]]></title>
<link>http://dddonruby.wordpress.com/2009/06/08/my-aproach-for-doing-ddd-on-ruby-introduction-and-part-i/</link>
<pubDate>Mon, 08 Jun 2009 04:29:47 +0000</pubDate>
<dc:creator>Fábio Rehm</dc:creator>
<guid>http://dddonruby.wordpress.com/2009/06/08/my-aproach-for-doing-ddd-on-ruby-introduction-and-part-i/</guid>
<description><![CDATA[Introduction We all know that in Domain-Driven Design it is good to express our domain with simplici]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><h2>Introduction</h2>
<p>We all know that in Domain-Driven Design it is good to express our domain with simplicity and &#8220;pureness&#8221; and for that we usually go for a POxO (Plain Old <em>{fill_with_your_preffered_language}</em> Object) approach. The problem is that the ORM solutions I&#8217;ve found for Ruby make us either inherit from some base class or do the mappings directly into our classes. By no means am I saying that they aren&#8217;t good, but we are talking about DDD and the idea of having a pure domain layer without distractions is something we should embrace.</p>
<p>My first thought was to write about a full blown example, comparing side by side a common C# / Java implementations to my Ruby implementation but then I realized it would probably have some unnecessary and &#8220;boring&#8221; information. It&#8217;s better to focus on writing about my approach and have some comments here and there to explain how things would be done in other platforms. What I&#8217;m going to show here is something that is really common in other languages but not in Ruby I believe, all classes from my domain will be implemented as POROs &#8211; Plain Old Ruby Objects, totaly decoupled from any tool that we might use.</p>
<p>There was a talk by Eric Evans called <a href="http://domaindrivendesign.org/node/80" target="_blank">&#8220;What I&#8217;ve learned about DDD since the book&#8221;</a> that has been commented out <a href="http://www.markhneedham.com/blog/2009/03/13/qcon-london-2009-what-ive-learned-about-ddd-since-the-book-eric-evans/" target="_blank">here</a> and <a href="http://gojko.net/2009/03/12/qcon-london-2009-eric-evans-what-ive-learned-about-ddd-since-the-book/" target="_blank">here</a> (<a href="http://qconlondon.com/london-2009/file?path=/qcon-london-2009/slides/EricEvans_WhatIveLearnedAboutDDDSinceTheBook.pdf" target="_blank">slides here</a>). Even though the building blocks of Model-Driven Design mentioned in the book (and the <a href="http://dddsample.sourceforge.net/characterization.html#Domain_Event">other one</a> mentioned on the talk) are not essential, they are important and will be the subject of this series.</p>
<p>So, to illustrate my ideas I&#8217;ll use the common Customer/Order/Product for my examples with some requirements from <a href="http://www.amazon.com/Applying-Domain-Driven-Design-Patterns-Examples/dp/0321268202" target="_blank">Jimmy Nilsson &#8211; Applying Domain-Driven Design and Patterns</a>:</p>
<ul>
<li>List the orders when looking at a specific customer</li>
<li>Orders have an acceptance status that is changed by the user</li>
<li>The total value of an order must be lower or equal than one million US$</li>
<li>A Customer has a credit limit and cannot owe us more than a specified amount of money</li>
</ul>
<h2>Part I &#8211; Customer and Products</h2>
<p>If you are not familiar with DDD and its building blocks I suggest that have a look at this <a href="http://domaindrivendesign.org/resources/ddd_terms" target="_blank">glossary of DDD terms</a>.</p>
<p>This is our really simple model for this part:</p>
<p style="text-align:center;"><img class="size-medium wp-image-104 aligncenter" title="model" src="http://dddonruby.wordpress.com/files/2009/05/exemplo-blog-model-part-1.jpg?w=300" alt="model" width="300" height="148" /></p>
<h2>Entities</h2>
<p>There&#8217;s no big deal here so I&#8217;ll just provide some code:</p>
<pre style="color:#d1d1d1;background:#000000;font-size:12px;"><span style="color:#e66170;font-weight:bold;">class</span> Customer
  attr_reader :id
  attr_accessor :name
  attr_accessor :credit_limit

  <span style="color:#e66170;font-weight:bold;">def</span> initialize<span style="color:#d2cd86;">(</span>name, credit_limit)
    @name <span style="color:#d2cd86;">=</span> name
    @credit_limit <span style="color:#d2cd86;">=</span> credit_limit
  <span style="color:#e66170;font-weight:bold;">end</span>
<span style="color:#e66170;font-weight:bold;">end</span>

<span style="color:#e66170;font-weight:bold;">class</span> Product
  attr_reader :id
  attr_accessor :price
  attr_accessor :description

  <span style="color:#e66170;font-weight:bold;">def</span> initialize<span style="color:#d2cd86;">(</span>price, description<span style="color:#d2cd86;">)</span>
    @price <span style="color:#d2cd86;">=</span> price
    @description <span style="color:#d2cd86;">=</span> description
  <span style="color:#e66170;font-weight:bold;">end</span>
<span style="color:#e66170;font-weight:bold;">end</span></pre>
<h2>Repositories</h2>
<p>Statically typed languages like Java and C# would have an interface in order to decouple our domain from infrastructure but Ruby doesn&#8217;t have interfaces. But still&#8230; I believe that we need some kind of <a href="http://en.wikipedia.org/wiki/Design_by_contract">contract</a> for the repositories and instead of having a class with empty methods I&#8217;ll create in-memory repositories as the <a href="http://www.martinfowler.com/eaaCatalog/repository.html" target="_blank">pattern definition</a>:</p>
<pre style="color:#d1d1d1;background:#000000;font-size:12px;"><span style="color:#e66170;font-weight:bold;">class</span> CustomerRepository
  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>store<span style="color:#d2cd86;">(</span>customer<span style="color:#d2cd86;">)</span>
    customer<span style="color:#d2cd86;">.</span>instance_variable_set<span style="color:#d2cd86;">(</span>:@id, next_id<span style="color:#d2cd86;">)</span> <span style="color:#e66170;font-weight:bold;">if</span> customer<span style="color:#d2cd86;">.</span>id<span style="color:#d2cd86;">.</span><span style="color:#e66170;font-weight:bold;">nil</span>?
    customers<span style="color:#d2cd86;">[</span>customer<span style="color:#d2cd86;">.</span>id<span style="color:#d2cd86;">]</span> <span style="color:#d2cd86;">=</span> customer
  <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>find<span style="color:#d2cd86;">(</span>id<span style="color:#d2cd86;">)</span>
    customers<span style="color:#d2cd86;">[</span>id<span style="color:#d2cd86;">]</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>all
    customers<span style="color:#d2cd86;">.</span>values
  <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>delete<span style="color:#d2cd86;">(</span>customer<span style="color:#d2cd86;">)</span>
    customers<span style="color:#d2cd86;">.</span>delete<span style="color:#d2cd86;">(</span>customer<span style="color:#d2cd86;">.</span>id<span style="color:#d2cd86;">)</span>
  <span style="color:#e66170;font-weight:bold;">end</span>  

  private  

  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>customers
<span style="color:#e66170;font-weight:bold;">    if</span> !<span style="color:#e66170;font-weight:bold;">defined</span>?<span style="color:#d2cd86;">(</span>@@customers<span style="color:#d2cd86;">)</span>
      @@customers <span style="color:#d2cd86;">=</span> <span style="color:#b060b0;">{</span><span style="color:#b060b0;">}</span>
    <span style="color:#e66170;font-weight:bold;">else</span>
      @@customers
    <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>next_id
<span style="color:#e66170;font-weight:bold;">    if</span> !<span style="color:#e66170;font-weight:bold;">defined</span>?<span style="color:#d2cd86;">(</span>@@next_id<span style="color:#d2cd86;">)</span>
      @@next_id <span style="color:#d2cd86;">=</span> <span style="color:#008c00;">1</span>
    <span style="color:#e66170;font-weight:bold;">else</span>
      @@next_id <span style="color:#d2cd86;">+</span><span style="color:#d2cd86;">=</span> <span style="color:#008c00;">1</span>
    <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
<span style="color:#e66170;font-weight:bold;">end</span>

<span style="color:#e66170;font-weight:bold;">class</span> ProductRepository
  <span style="color:#99cc00;"><em><span style="font-weight:bold;"># ... similar code</span></em></span><em> <span style="color:#99cc00;">...</span></em>
<span style="color:#e66170;font-weight:bold;">end</span></pre>
<p>Maybe this code could be factored out somewhere but let&#8217;s just leave as it is for now.</p>
<p>Right now you might be thinking &#8220;This guy is crazy, static methods are evil!!&#8221;. Well, I think that <a href="http://blog.jayfields.com/2007/04/ruby-class-methods.html" target="_blank">it&#8217;s not true</a> when it comes to Ruby class methods. Just below I will show you how we can easily add persistence to our domain.</p>
<p>Even if we want to set up a <a href="http://www.martinfowler.com/articles/injection.html">IoC container</a> I don&#8217;t think it would be a problem since <a href="http://ruby-doc.org/core/classes/Class.html">Ruby classes are objects as well</a>. For example these repositories could be easily injected into a Rails controller instance variable.</p>
<h2>Adding persistence</h2>
<p>If we use (N)Hibernate, we would probably have the mappings file into a different package / assembly, but in Ruby I think it would be enough to just have persistence related code in another file that redefines the classes.</p>
<h3>Mappings</h3>
<pre style="color:#d1d1d1;background:#000000;font-size:12px;"><span style="color:#e66170;font-weight:bold;">class</span> Customer
  include Clipper::Model

  orm<span style="color:#d2cd86;">.</span>map<span style="color:#d2cd86;">(</span><span style="color:#e66170;font-weight:bold;">self</span>, <span style="color:#00c4c4;">"customers"</span><span style="color:#d2cd86;">)</span> <span style="color:#e66170;font-weight:bold;">do</span> &#124;customers&#124;
    customers<span style="color:#d2cd86;">.</span>key<span style="color:#d2cd86;">(</span>customers<span style="color:#d2cd86;">.</span>field<span style="color:#d2cd86;">(</span><span style="color:#00c4c4;">"id"</span>, Clipper::Types::Serial<span style="color:#d2cd86;">)</span><span style="color:#d2cd86;">)</span>
    customers<span style="color:#d2cd86;">.</span>field<span style="color:#d2cd86;">(</span><span style="color:#00c4c4;">"name"</span>, Clipper::Types::<span style="color:#e66170;font-weight:bold;">String</span><span style="color:#d2cd86;">.</span><span style="color:#e66170;font-weight:bold;">new</span><span style="color:#d2cd86;">(</span><span style="color:#008c00;">200</span><span style="color:#d2cd86;">)</span><span style="color:#d2cd86;">)</span>
    customers<span style="color:#d2cd86;">.</span>field<span style="color:#d2cd86;">(</span><span style="color:#00c4c4;">"credit_limit"</span>, Clipper::Types::<span style="color:#e66170;font-weight:bold;">Float</span><span style="color:#d2cd86;">(</span><span style="color:#008c00;">8</span>, <span style="color:#008c00;">2</span><span style="color:#d2cd86;">)</span><span style="color:#d2cd86;">)</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
<span style="color:#e66170;font-weight:bold;">end</span>

<span style="color:#e66170;font-weight:bold;">class</span> Product
  include Clipper::Model

  orm<span style="color:#d2cd86;">.</span>map<span style="color:#d2cd86;">(</span><span style="color:#e66170;font-weight:bold;">self</span>, <span style="color:#00c4c4;">"products"</span><span style="color:#d2cd86;">)</span> <span style="color:#e66170;font-weight:bold;">do</span> &#124;products&#124;
    products<span style="color:#d2cd86;">.</span>key<span style="color:#d2cd86;">(</span>products<span style="color:#d2cd86;">.</span>field<span style="color:#d2cd86;">(</span><span style="color:#00c4c4;">"id"</span>, Clipper::Types::Serial<span style="color:#d2cd86;">)</span><span style="color:#d2cd86;">)</span>
    products<span style="color:#d2cd86;">.</span>field<span style="color:#d2cd86;">(</span><span style="color:#00c4c4;">"description"</span>, Clipper::Types::<span style="color:#e66170;font-weight:bold;">String</span><span style="color:#d2cd86;">.</span><span style="color:#e66170;font-weight:bold;">new</span><span style="color:#d2cd86;">(</span><span style="color:#008c00;">200</span><span style="color:#d2cd86;">)</span><span style="color:#d2cd86;">)</span>
    products<span style="color:#d2cd86;">.</span>field<span style="color:#d2cd86;">(</span><span style="color:#00c4c4;">"price"</span>, Clipper::Types::<span style="color:#e66170;font-weight:bold;">Float</span><span style="color:#d2cd86;">(</span><span style="color:#008c00;">8</span>, <span style="color:#008c00;">2</span><span style="color:#d2cd86;">)</span><span style="color:#d2cd86;">)</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
<span style="color:#e66170;font-weight:bold;">end</span></pre>
<h3>Repositories</h3>
<pre style="color:#d1d1d1;background:#000000;font-size:12px;"><span style="color:#e66170;font-weight:bold;">module</span> ClipperRepository
  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>included<span style="color:#d2cd86;">(</span>klass<span style="color:#d2cd86;">)</span>
    klass<span style="color:#d2cd86;">.</span>instance_eval <span style="color:#e66170;font-weight:bold;">do</span>
      include Singleton
      include Clipper::Session::Helper

      <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>orm
        instance<span style="color:#d2cd86;">.</span>orm
      <span style="color:#e66170;font-weight:bold;">end</span>
    <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
<span style="color:#e66170;font-weight:bold;">end</span>

<span style="color:#e66170;font-weight:bold;">class</span> CustomerRepository
  include ClipperRepository

  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>store<span style="color:#d2cd86;">(</span>customer<span style="color:#d2cd86;">)</span>
    orm<span style="color:#d2cd86;">.</span>save<span style="color:#d2cd86;">(</span>customer<span style="color:#d2cd86;">)</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>delete<span style="color:#d2cd86;">(</span>customer<span style="color:#d2cd86;">)</span>
    orm<span style="color:#d2cd86;">.</span>delete<span style="color:#d2cd86;">(</span>customer<span style="color:#d2cd86;">)</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>find<span style="color:#d2cd86;">(</span>id<span style="color:#d2cd86;">)</span>
    orm<span style="color:#d2cd86;">.</span>get<span style="color:#d2cd86;">(</span>Customer, id<span style="color:#d2cd86;">)</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#e66170;font-weight:bold;">def</span> self<span style="color:#d2cd86;">.</span>all
    orm<span style="color:#d2cd86;">.</span>all<span style="color:#d2cd86;">(</span>Customer<span style="color:#d2cd86;">)</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
<span style="color:#e66170;font-weight:bold;">end</span>

<span style="color:#e66170;font-weight:bold;">class</span> ProductRepository
  <span style="color:#99cc00;"><em><span style="font-weight:bold;"># ... similar cod</span><span style="font-weight:bold;"><span style="color:#99cc00;">e</span></span></em></span><em> </em><span style="color:#e66170;font-weight:bold;"><em><span style="color:#99cc00;"> ...</span></em>
end</span></pre>
<p>Here I&#8217;ve used <a href="http://github.com/wiecklabs/clipper/tree/master" target="_blank">Clipper </a>but for these examples we could probably rewrite it to use <a href="http://datamapper.org/">DataMapper</a> as well. Unfortunately, with this approach both DataMapper and Clipper will redefine our already defined accessors and that would be a problem if we have some business logic there. For this example this wouldn&#8217;t be a problem but I&#8217;ve checked with one of Clipper developers and they are willing to have this feature implemented in the library, I&#8217;ll have to check if DataMapper folks have something like this in mind as well. I&#8217;ve already hacked Clipper in order to have something like Hibernate <a href="http://docs.jboss.org/hibernate/stable/core/reference/en/html/mapping.html#mapping-declaration-property" target="_blank">property access config</a> that defines the strategy for accessing the property value but it still lacks the feature for associations.<strong></strong></p>
<h2>Testing</h2>
<p>With this approach I believe testing becomes more simple. I&#8217;ve created tests for the pure domain and just by including a different file I can test everything hooked up with infrastructure without rewriting the tests. To make things easier, I created two Rake tasks for testing: &#8216;rake test:domain&#8217; and &#8216;rake test:infrastructure&#8217;. I think they look a bit ugly at the moment but here we go:</p>
<pre style="color:#d1d1d1;background:#000000;font-size:12px;">namespace :<span style="color:#e66170;font-weight:bold;">test</span> <span style="color:#e66170;font-weight:bold;">do</span>
  task :enviroment_domain <span style="color:#e66170;font-weight:bold;">do</span> &#124;t&#124;
    ENV<span style="color:#d2cd86;">[</span><span style="color:#00c4c4;">'DDD_EXAMPLE_HELPER'</span><span style="color:#d2cd86;">]</span> <span style="color:#d2cd86;">=</span> Pathname<span style="color:#d2cd86;">(</span>__FILE__<span style="color:#d2cd86;">)</span><span style="color:#d2cd86;">.</span>dirname <span style="color:#d2cd86;">+</span> <span style="color:#00c4c4;">'tests'</span> <span style="color:#d2cd86;">+</span> <span style="color:#00c4c4;">'domain_helper'</span>
  <span style="color:#e66170;font-weight:bold;">end</span>

  task :enviroment_infrastructure <span style="color:#e66170;font-weight:bold;">do</span> &#124;t&#124;
    ENV<span style="color:#d2cd86;">[</span><span style="color:#00c4c4;">'DDD_EXAMPLE_HELPER'</span><span style="color:#d2cd86;">]</span> <span style="color:#d2cd86;">=</span> Pathname<span style="color:#d2cd86;">(</span>__FILE__<span style="color:#d2cd86;">)</span><span style="color:#d2cd86;">.</span>dirname <span style="color:#d2cd86;">+</span> <span style="color:#00c4c4;">'tests'</span> <span style="color:#d2cd86;">+</span> <span style="color:#00c4c4;">'infrastructure_helper'</span>
  <span style="color:#e66170;font-weight:bold;">end</span>

  Rake::TestTask<span style="color:#d2cd86;">.</span><span style="color:#e66170;font-weight:bold;">new</span><span style="color:#d2cd86;">(</span>:domain <span style="color:#d2cd86;">=</span>&#62; :enviroment_domain<span style="color:#d2cd86;">)</span> <span style="color:#e66170;font-weight:bold;">do</span> &#124;t&#124;
    t<span style="color:#d2cd86;">.</span>libs &#60;&#60; <span style="color:#00c4c4;">"tests"</span>
    t<span style="color:#d2cd86;">.</span>test_files <span style="color:#d2cd86;">=</span> FileList<span style="color:#d2cd86;">[</span><span style="color:#00c4c4;">"tests/domain/**/*_test.rb"</span><span style="color:#d2cd86;">]</span>
    t<span style="color:#d2cd86;">.</span>verbose <span style="color:#d2cd86;">=</span> <span style="color:#e66170;font-weight:bold;">true</span>
  <span style="color:#e66170;font-weight:bold;">end</span>

  Rake::TestTask<span style="color:#d2cd86;">.</span><span style="color:#e66170;font-weight:bold;">new</span><span style="color:#d2cd86;">(</span>:infrastructure <span style="color:#d2cd86;">=</span>&#62; :enviroment_infrastructure<span style="color:#d2cd86;">)</span> <span style="color:#e66170;font-weight:bold;">do</span> &#124;t&#124;
    t<span style="color:#d2cd86;">.</span>libs &#60;&#60; <span style="color:#00c4c4;">"tests"</span>
    t<span style="color:#d2cd86;">.</span>test_files <span style="color:#d2cd86;">=</span> FileList<span style="color:#d2cd86;">[</span><span style="color:#00c4c4;">"tests/domain/**/*_test.rb"</span><span style="color:#d2cd86;">]</span> <span style="color:#d2cd86;">+</span> FileList<span style="color:#d2cd86;">[</span><span style="color:#00c4c4;">"tests/infrastructure/**/*_test.rb"</span><span style="color:#d2cd86;">]</span>
    t<span style="color:#d2cd86;">.</span>verbose <span style="color:#d2cd86;">=</span> <span style="color:#e66170;font-weight:bold;">true</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
<span style="color:#e66170;font-weight:bold;">end</span></pre>
<h3>Test Case</h3>
<pre style="color:#d1d1d1;background:#000000;font-size:12px;"><span style="color:#e66170;font-weight:bold;">require</span> ENV<span style="color:#d2cd86;">[</span><span style="color:#00c4c4;">'DDD_EXAMPLE_HELPER'</span><span style="color:#d2cd86;">]</span>

<span style="color:#e66170;font-weight:bold;">class</span> CustomerRepositoryTest &#60; Test::Unit::TestCase
  <span style="color:#9999a9;"># ...</span>
  <span style="color:#e66170;font-weight:bold;">def</span> test_create
    customer <span style="color:#d2cd86;">=</span> Customer<span style="color:#d2cd86;">.</span><span style="color:#e66170;font-weight:bold;">new</span><span style="color:#d2cd86;">(</span><span style="color:#00c4c4;">'customer'</span>, <span style="color:#008c00;">1500</span><span style="color:#d2cd86;">)</span>
    CustomerRepository<span style="color:#d2cd86;">.</span>store<span style="color:#d2cd86;">(</span>customer<span style="color:#d2cd86;">)</span>
    assert_not_nil<span style="color:#d2cd86;">(</span>customer<span style="color:#d2cd86;">.</span>id<span style="color:#d2cd86;">)</span>
  <span style="color:#e66170;font-weight:bold;">end</span>
  <span style="color:#9999a9;"># ...</span>
<span style="color:#e66170;font-weight:bold;">end</span></pre>
<p>I believe this approach increases experimentation because we are free to work with our domain without worrying about persistence issues as if we were using Rails ActiveRecord. Rails AR need us to set up DB tables by running migrations in order to use the entities and have access to the properties.</p>
<h2>Project Structure</h2>
<p><img class="aligncenter size-full wp-image-108" title="structure" src="http://dddonruby.wordpress.com/files/2009/05/structure1.jpg" alt="structure" width="280" height="673" /></p>
<h2>Conclusion</h2>
<p>This whole thing might seem weird if you are used to Rails AR, but the fact that we have our domain totaly decoupled from infrastructure issues is important because as technology changes and shifts, and as our domain layer is burdened with complex computer science problems, things will most certainly change.  Keeping the <a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">heart of the software</a> decoupled from tools allows those changes to be easier (XP ?).</p>
<p>That&#8217;s it! I&#8217;d like to thank <a href="http://blog.michaelbrennan.net/">Michael Brennan</a> and <a href="http://guilherme.pro/">Guilherme Chapiewski</a> for reviewing  and contributing with ideas for this post and <a href="http://www.linkedin.com/pub/sam-smoot/6/23b/881">Sam Smoot</a> for also reviewing and helping me out with Clipper.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Foutaises, apprenez à les détecter]]></title>
<link>http://apatricio.wordpress.com/2009/05/15/foutaises-apprenez-a-les-detecter/</link>
<pubDate>Fri, 15 May 2009 12:21:46 +0000</pubDate>
<dc:creator>apatricio</dc:creator>
<guid>http://apatricio.wordpress.com/2009/05/15/foutaises-apprenez-a-les-detecter/</guid>
<description><![CDATA[Tout travail mérite le respect, la réflexion et le temps passé à concevoir et implémenter une soluti]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Tout travail mérite le respect, la réflexion et le temps passé à concevoir et implémenter une solution ne peuvent être directement et gratuitement fustigés.</p>
<p>Il en va différemment lorsque les auteurs s&#8217;exposent eux-mêmes en lançant une information agressive et fausse (aka <a href="http://fr.wikipedia.org/wiki/Fear,_uncertainty_and_doubt" target="_blank">F.U.D</a>) avec d&#8217;autres produits.</p>
<p>C&#8217;est ce qu&#8217;il s&#8217;est passé <a href="http://www.theserverside.com/news/bookmark!add.jspa?forumID=2&#38;threadID=54535">ici</a> où l&#8217;on nous ressort un DataMapper basé sur des patterns anciens voire du millénaire passé comme commenté sur la page:</p>
<blockquote><p>Honestly, the approach is old. I know that I&#8217;ve used similar approach going back to 1999 and it was old back then.</p></blockquote>
<p>Reprenons depuis le début, le produit présenté n&#8217;a rien d&#8217;un ORM (Object Relationnal Mapping) dès lors qu&#8217;il impose d&#8217;énormes limitations au modèle objet, comme la non prise en charge de l&#8217;héritage et surtout qu&#8217;il ne propose pas de mapping&#8230; ben oui forcément. Ici il s&#8217;agit en fait d&#8217;imposer, via un framework, une organisation/une structuration du code dans des classes stéréotypées. L&#8217;idée est louable, toujours meilleures que d&#8217;avoir du JDBC pur non organisé et explosé partout dans un projet.</p>
<p>Cependant, c&#8217;est assez préhistorique et très franchement pénalisant sur beaucoup de points, lisons entre les lignes :</p>
<blockquote><p>No lazy loading. Just eager loading because you can expect whatever you want during coding. Eager loading removes n + 1 queries.</p></blockquote>
<p>Mouais, c&#8217;est un peu beaucoup n&#8217;importe quoi. Le lazy loading peut effectivement entraîner un soucis de <em>n + 1 requête</em>s mais <span style="text-decoration:underline;"><strong>uniquement</strong></span><strong> </strong>si le développeur est un lazy développeur (= développeur fainéant). Avec un ORM et hibernate en particulier, tout est fait pour pouvoir optimiser les modes de récupération de graphe d&#8217;objets. En passant &#8220;just eager loading&#8221; tend à forcer le chargement entier des graphes d&#8217;objets. Ceci est purement unitle et simplement consommateur de ressources. D&#8217;où l&#8217;existence d&#8217;une fonctionnalité comme le <em>lazy loading</em> qui permet de charger uniquement la portion de graphe nécessaire à un cas d&#8217;utilisation. Le <em>lazy loading</em> bouchonne le reste du graphe avec des <em>proxies</em> qui permettront eux-même le chargement transparent du reste du graphe en cas de nécessité, comprende? &#8230; la boucle est bouclée</p>
<blockquote><p>an entity object which extends <strong><em>POJO</em></strong></p></blockquote>
<p>Comme le dirait un de mes bons amis:  &#8220;<em>namuf</em> ?&#8221; (= quoi?, <em>kékidi</em>? ou encore C&#8217;est une blague?). Pour faire court, simple et pour ceux qui n&#8217;ont pas tilté, un <em>POJO </em>est un objet pur, qui ne dépend d&#8217;aucun framework, encore moins technique. Un <em>POJO </em>est libre et peut être exploité par un client sans que l&#8217;on ait besoin de déployer une quelconque armada de jars de frameworks techniques au risque de se prendre une <em>ClassNotFoundException</em>.</p>
<p>Notre ami nous explique donc que les classes persistantes utilisées avec son framework doivent étendre une classe technique, présente dans son framework, classe qui se nomme très intelligemment <em>POJO</em>. C&#8217;est fantastique! Forcément et probablement sans même savoir pourquoi, il a du compléter son framework de convertisseurs:</p>
<blockquote><p>built-in converter that can be used to convert a Java Object into a frontend String or a frontend String into a backend Java Object. The converter prevents data conversion from scattering different pages and layers.</p></blockquote>
<p>Beh oui, les objets n&#8217;étant pas des <em>POJOS</em>, ils deviennent difficilement manipulables d&#8217;une couche à l&#8217;autre. Il faut passer par le bon vieux <em>DTO</em>, à savoir un <em>POJO </em>destiné essentiellement à des fins de manipulation de données. Et pour automatiser la transposition d&#8217;un &#8220;<em>truc</em>&#8221; (désolé ses trucs ne sont pas des <em>POJOS </em>pour moi) vers un DTO, que faut-il? Des convertisseurs, bravo. Il va forcément falloir gérer ces conversions de manière systématique, typiquement entre la couche service et la couche web.</p>
<p>Ces traitements sont coûteux en terme de développement et de maintenance, complètement inutile car ne contenant aucune plu value métier et forcément c&#8217;est vraiment contre productif. Mais non puisque notre ami nous affirme gratuitement:</p>
<blockquote><p>High productivity compared to Hibernate.</p></blockquote>
<p>Sans exagérer 70% de ce que dit l&#8217;auteur est faux et je vais arréter là, &#8230; euh, &#8230; aller une dernière pour la route, lisez attentivement le titre est les premiers mots du <a href="http://www.theserverside.com/news/thread.tss?thread_id=54535&#38;m=bm.added#308576" target="_blank">commentaire ici</a> (écrit par l&#8217;auteur du framework lui-même. ):</p>
<blockquote>
<h2>No limitation</h2>
</blockquote>
<p>suivi de</p>
<blockquote><p>There are no polymorphic queries</p></blockquote>
<p>Comme c&#8217;est beau, il m&#8217;a convaincu!</p>
<p>Tout ceci ne veut pas dire que le framework est inutile ou mauvais, il ne répond simplement pas à un outil du spectre d&#8217;un ORM. En le aisant délibérement, l&#8217;auteur s&#8217;est tiré une balle dans le pied.</p>
<p>J&#8217;ai connu et connais encore plusieurs décideurs qui se laissent berner par ce type d&#8217;argumentation. Résultat: des applications qui utilisent des technos d&#8217;un autre millénaire (ce qui n&#8217;est pas grave) mais qui passent aussi à côté de technos pouvant résuire sensiblement les coûts de développement, de maintenance et d&#8217;évolution. Prenez une application de 50 tables avec 1000 requêtes SQL codées en dure, forcément pas le choix avec un DataMapper, il faut en coder une par cas d&#8217;utilisation. Ajoutez une colonne par ci par là lors d&#8217;une évolution, vous m&#8217;en direz des nouvelles&#8230;</p>
<p>Apprenez à lire entre les lignes et si vous êtes décideur sans être expert sur un sujet en particulier, déléguez à un de vos petits gars passionnés. Il vous fera gagner beaucoup d&#8217;argent à terme, croyez-moi. De même, méfiez-vous toujours des <em>software marabous</em> qui vous vendent une bidouille propriétaire  sortie du chapeau et qui vous certifie qu&#8217;elle est bien meilleure que les frameworks les plus robustes, matures et éprouvés.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Third party user authentication with Ruby in a just few lines of code]]></title>
<link>http://blog.saush.com/2009/04/25/third-party-user-authentication-with-ruby-in-a-just-few-lines-of-code/</link>
<pubDate>Fri, 24 Apr 2009 16:05:44 +0000</pubDate>
<dc:creator>sausheong</dc:creator>
<guid>http://blog.saush.com/2009/04/25/third-party-user-authentication-with-ruby-in-a-just-few-lines-of-code/</guid>
<description><![CDATA[Some time ago (8 years to be exact) when I was still chest-deep in Java and working in elipva, I wro]]></description>
<content:encoded><![CDATA[Some time ago (8 years to be exact) when I was still chest-deep in Java and working in elipva, I wro]]></content:encoded>
</item>
<item>
<title><![CDATA[Clone TinyURL in 40 lines of Ruby code]]></title>
<link>http://blog.saush.com/2009/04/13/clone-tinyurl-in-40-lines-of-ruby-code/</link>
<pubDate>Mon, 13 Apr 2009 05:09:43 +0000</pubDate>
<dc:creator>sausheong</dc:creator>
<guid>http://blog.saush.com/2009/04/13/clone-tinyurl-in-40-lines-of-ruby-code/</guid>
<description><![CDATA[I&#8217;m officially hooked. After writing 2 blog posts on cloning popular web applications on the I]]></description>
<content:encoded><![CDATA[I&#8217;m officially hooked. After writing 2 blog posts on cloning popular web applications on the I]]></content:encoded>
</item>
<item>
<title><![CDATA[JavaScript фреймворк Helma в GAE/J]]></title>
<link>http://reversengineer.wordpress.com/2009/04/12/helma-in-appengine/</link>
<pubDate>Sun, 12 Apr 2009 18:49:32 +0000</pubDate>
<dc:creator>Reverse Engineer</dc:creator>
<guid>http://reversengineer.wordpress.com/2009/04/12/helma-in-appengine/</guid>
<description><![CDATA[Нашел интересную заметку у Roberto Saccon по поводу запуска Helma в GAE/J. Helma &#8211; это server-]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Нашел интересную заметку у <a href="http://www.rsaccon.com/2009/04/helma-ng-serverside-javascript.html" target="_blank">Roberto Saccon</a> по поводу запуска Helma в GAE/J. Helma &#8211; это server-side фреймворк, написанный на Java. Языком для разработки выступает JavaScript, что делает этот фреймворк крайне интересным.</p>
<p>Мне кажется, GAE/J своим стартом дал дорогу многим интересным проектам, не только JRuby. Конечно все целиком зависит от задач, но Sinatra в GAE/J смотриться куда более органично, нежели Rails. А упор на BigTable должен поднять интерес к таким проектам как DataMapper. В ActiveRecord DataStore уже не влезет.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Getting started with DataMapper]]></title>
<link>http://usingimho.wordpress.com/2009/02/15/getting-started-with-datamapper/</link>
<pubDate>Sun, 15 Feb 2009 09:33:01 +0000</pubDate>
<dc:creator>andreadallera</dc:creator>
<guid>http://usingimho.wordpress.com/2009/02/15/getting-started-with-datamapper/</guid>
<description><![CDATA[The most famous and widespread ruby ORM is undoubtly ActiveRecord, due to the fact that it comes in ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>The most famous and widespread ruby ORM is undoubtly ActiveRecord, due to the fact that it comes in bundle with Ruby on Rails. But, has it often happens, that doesn&#8217;t mean it&#8217;s the best choice : DataMapper has a number of additional features (lazy loading, strategic eager loading &#8211; no need to check for possible select + 1 problems), implements the <a href="http://en.wikipedia.org/wiki/Identity_map">identity map</a> pattern and it&#8217;s WAY faster than its counterpart.<br />
First thing that you need to do is to install the related gem, so open up a command prompt, log in as root and type :<br />
<code><br />
gem install data_mapper<br />
</code><br />
After that you will be able to use the DataMapper module inside your Ruby application just with :<br />
<code><br />
require 'rubygems'<br />
require 'dm-core'<br />
</code><br />
If you have an instance of MySql available you can connect to it using :<br />
<code><br />
DataMapper.setup(:default, 'mysql://user:password@hostname/dbname')<br />
</code><br />
For those of you who are acquainted to (N)Hibernate this is maybe the big point, as there&#8217;s no need to write mapping files (or attributes, or whatever). All that you need to leverage DataMapper is to include <em>DataMapper::Resource</em> in your class.<br />
<code><br />
class Customer<br />
include DataMapper::Resource</code></p>
<p>property :id, Integer, :serial =&#62; true<br />
property :name, String<br />
property :surname, String<br />
has n, :bills<br />
belongs_to :customergroup</p>
<p>end<br />
Convention over configuration : unless you explicitly declare it, tables in the database take the plural declination of your business entity&#8217;s name (customer -&#62; customers) and foreign key columns are in the format (parententityname)_id: in this case it will be customergroup_id.<br />
DataMapper implements the <a href="http://en.wikipedia.org/wiki/Active_record_pattern">active record</a> pattern, so each entity is responsible for its own persistence<br />
<code><br />
my_customer = Customer.new<br />
...<br />
my_customer.save<br />
</code><br />
Data retrieval is done via class methods, like this:<br />
<code><br />
my_customers = Customer.all<br />
my_customers = Customer.get(4) #gets the customer with id = 4<br />
my_customers = Customer.all(:name =&#62; "John", :surname =&#62; "Smith") # SELECT * FROM customers WHERE name = "John" AND surname = "Smith"<br />
</code><br />
More on <a href="http://www.datamapper.org/">DataMapper&#8217;s site</a>. A more detailed quickstart available <a href="http://www.andreadallera.com/blog/dmtest.zip">here</a>.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Getting started with DataMapper]]></title>
<link>http://andreadallera.wordpress.com/2009/02/15/getting-started-with-datamapper/</link>
<pubDate>Sun, 15 Feb 2009 09:33:01 +0000</pubDate>
<dc:creator>andreadallera</dc:creator>
<guid>http://andreadallera.wordpress.com/2009/02/15/getting-started-with-datamapper/</guid>
<description><![CDATA[The most famous and widespread ruby ORM is undoubtly ActiveRecord, due to the fact that it comes in ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>The most famous and widespread ruby ORM is undoubtly ActiveRecord, due to the fact that it comes in bundle with Ruby on Rails. But, has it often happens, that doesn&#8217;t mean it&#8217;s the best choice : DataMapper has a number of additional features (lazy loading, strategic eager loading &#8211; no need to check for possible select + 1 problems), implements the <a href="http://en.wikipedia.org/wiki/Identity_map">identity map</a> pattern and it&#8217;s WAY faster than its counterpart.<br />
First thing that you need to do is to install the related gem, so open up a command prompt, log in as root and type :<br />
<code><br />
gem install data_mapper<br />
</code><br />
After that you will be able to use the DataMapper module inside your Ruby application just with :<br />
<code><br />
require 'rubygems'<br />
require 'dm-core'<br />
</code><br />
If you have an instance of MySql available you can connect to it using :<br />
<code><br />
DataMapper.setup(:default, 'mysql://user:password@hostname/dbname')<br />
</code><br />
For those of you who are acquainted to (N)Hibernate this is maybe the big point, as there&#8217;s no need to write mapping files (or attributes, or whatever). All that you need to leverage DataMapper is to include <em>DataMapper::Resource</em> in your class.<br />
<code><br />
class Customer<br />
include DataMapper::Resource</code></p>
<p>property :id, Integer, :serial =&#62; true<br />
property :name, String<br />
property :surname, String<br />
has n, :bills<br />
belongs_to :customergroup</p>
<p>end<br />
Convention over configuration : unless you explicitly declare it, tables in the database take the plural declination of your business entity&#8217;s name (customer -&#62; customers) and foreign key columns are in the format (parententityname)_id: in this case it will be customergroup_id.<br />
DataMapper implements the <a href="http://en.wikipedia.org/wiki/Active_record_pattern">active record</a> pattern, so each entity is responsible for its own persistence<br />
<code><br />
my_customer = Customer.new<br />
...<br />
my_customer.save<br />
</code><br />
Data retrieval is done via class methods, like this:<br />
<code><br />
my_customers = Customer.all<br />
my_customers = Customer.get(4) #gets the customer with id = 4<br />
my_customers = Customer.all(:name =&#62; "John", :surname =&#62; "Smith") # SELECT * FROM customers WHERE name = "John" AND surname = "Smith"<br />
</code><br />
More on <a href="http://www.datamapper.org/">DataMapper&#8217;s site</a>. A more detailed quickstart available <a href="http://www.andreadallera.com/blog/dmtest.zip">here</a>.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Life On The Edge With Merb, DataMapper &amp; RSpec]]></title>
<link>http://thailehuy.wordpress.com/2009/01/28/life-on-the-edge-with-merb-datamapper-rspec/</link>
<pubDate>Wed, 28 Jan 2009 04:02:59 +0000</pubDate>
<dc:creator>thailehuy</dc:creator>
<guid>http://thailehuy.wordpress.com/2009/01/28/life-on-the-edge-with-merb-datamapper-rspec/</guid>
<description><![CDATA[Check out the great book for beginner at: http://book.merbist.com/ Merb, DataMapper and RSpec are al]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Check out the great book for beginner at: <a href="http://book.merbist.com/" target="_blank">http://book.merbist.com/</a></p>
<p>Merb, DataMapper and RSpec are all open source projects that are great for  building kick-ass web applications. They are all in active development and  although it can be hard, we&#8217;ll try our best to keep up-to-date.</p>
<h3><a href="http://merbivore.com/">Merb</a></h3>
<p>Merb is a relatively new web framework with an initial 0.0.1 release in October 2006.  <a href="http://brainspl.at/">Ezra Zygmuntowicz</a> is Merb&#8217;s creator, and  continues to actively develop Merb along with a dedicated development team at  <a href="http://www.engineyard.com/">Engine Yard</a> and many other community contributors.</p>
<p>Merb has obvious roots and inspiration in the  <a href="http://www.rubyonrails.com/">Ruby on Rails</a> web framework.  If you know Ruby and have used Rails you&#8217;re likely to get the hang of Merb quite easily.</p>
<p>While there are similarities, Merb is not Ruby on Rails. There are core differences in design and philosophy. In many areas that Rails chooses to be opinionated, Merb is agnostic &#8211; with respect to the ORM, the JavaScript library and template language. The Merb philosophy also disbelieves in having a monolithic framework. Instead, it consists of a number of modules distributed as Ruby gems. This means that it is possible to pick and choose the functionality you need, instead of cluttering up the framework with non-essential features.</p>
<p>The <code>merb</code> gem installs <code>merb-core</code>, a series of plugins as well as a default ORM (DataMapper); all you need in order to  get started straight away.  The benefit of this modularity is that the framework  remains simple and focused with additional functionality provided by gems.</p>
<p>Thanks to Merb&#8217;s modularity, you are not locked into using any particular  libraries. For example, Merb ships with plugins for several popular ORMs and  provides support for both Test::Unit and RSpec.</p>
<p><code>merb-core</code> alone provides a lightweight framework  (a la <a href="http://code.whytheluckystiff.net/camping/">camping</a>) that can be used to  create a simple web app such as an upload server or API provider where the  functionality of an all-inclusive framework is not necessary.</p>
<h3><a href="http://datamapper.org/">DataMapper</a></h3>
<p>DataMapper is an Object-Relational Mapper (ORM) written in Ruby by Sam Smoot.  We&#8217;ll be using DataMapper with Merb. As previously mentioned, Merb does not require  the use of DataMapper.  You can just as easily use the same ORM as Rails  (ActiveRecord) if you prefer.</p>
<p>We have chosen to use DataMapper because of it&#8217;s feature set and performance. One of the differences between it and ActiveRecord that I find useful is the way  database attributes are handled. The schema, migrations and attributes are all  defined in one place: your model. This means you no longer have to look around in  your database or other files to see what is defined.</p>
<p>While DataMapper has similarities to ActiveRecord, we will be highlighting the  differences as we go along.</p>
<h3><a href="http://rspec.info/">RSpec</a></h3>
<p>RSpec is a Behaviour Driven Development framework for Ruby. It consists of two main pieces, a Story framework for integration tests and a Spec framework for object tests. Both these components are implemented as Domain Specific Languages which help to make the stories and specs created more readable.</p>
<p>Merb currently supports the Test::Unit and RSpec testing frameworks. Both Merb and Datamapper use the RSpec testing frameworks and so we will be covering some aspects so that you may use it for your own applications.</p>
<h2>What About Ruby On Rails?</h2>
<blockquote><p>[Merb is] Harder, Better, Faster, Stronger, to quote Daft Punk &#8211; Max Williams</p></blockquote>
<p>So what&#8217;s the big deal? We have Ruby on Rails and that&#8217;s enough, isn&#8217;t it?  There is little doubt that Ruby on Rails has rocked the web application  development world. You have to give credit where credit&#8217;s due, and Ruby on Rails  is definitely a great web framework.  However, there is no such thing as a  one-size fits all solution.  Ruby on Rails is opinionated software which  provides many benefits such as Convention over Configuration.  On the other  hand, this also means that Ruby on Rails can be unforgiving if you don&#8217;t want  to do things &#8216;the Rails way&#8217;.</p>
<p>Where Rails is opinionated, Merb is agnostic. For example, you can easily use  your favourite ORM (ActiveRecord, DataMapper, Sequel) or none at all.<br />
Similarly, you can choose the Javascript library and template language that you  are most comfortable with, or that best meets the requirements of your specific  project.</p>
<p>If performant were a word, Merb would be it.  One of Merb&#8217;s design mantras is  &#8220;No code is faster than no code&#8221;.  Merb has super-fast routing and is  thread-safe. The core functionality is kept separate from the other plugins  and it uses less Ruby &#8216;magic&#8217;, making it easier to understand and hack.</p>
<p>Rails (and consequently Ruby) has received a lot of criticism for not being  suitable for large scale web applications, which isn&#8217;t necessarily true. Merb  has been built from the outset to prove that Ruby is a viable language for  building fast and scalable web applications.</p>
<p>At the end of the day it&#8217;s about choice. There are many new Ruby frameworks  springing up, undoubtedly encouraged by the success of Rails.  In our opinion, Merb shows the most promise of these.</p>
<p>If you&#8217;d like to take a look at some other frameworks these links should get you  started:</p>
<ul>
<li><a href="http://camping.rubyforge.org/files/README.html">http://camping.rubyforge.org/files/README.html</a></li>
<li><a href="http://www.nitroproject.org/">http://www.nitroproject.org/</a></li>
<li><a href="http://ramaze.rubyforge.org/">http://ramaze.rubyforge.org/</a></li>
<li><a href="http://sinatra.rubyforge.org/">http://sinatra.rubyforge.org/</a></li>
<li><a href="http://halcyon.rubyforge.org/">http://halcyon.rubyforge.org/</a></li>
<li><a href="http://wisteria.swiftcore.org/">http://wisteria.swiftcore.org/</a></li>
<li><a href="http://api.mackframework.com/">http://api.mackframework.com/</a></li>
</ul>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Double Shot #326]]></title>
<link>http://afreshcup.com/2008/11/04/double-shot-326/</link>
<pubDate>Tue, 04 Nov 2008 11:28:25 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2008/11/04/double-shot-326/</guid>
<description><![CDATA[Yesterday saw my first posting to the official Rails weblog. A nice step on the way to world dominat]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Yesterday saw my <a href="http://weblog.rubyonrails.org/2008/11/3/rails-guides-wants-you">first posting</a> to the official Rails weblog. A nice step on the way to world domination, I guess. </p>
</ul>
<li><strong><a href="http://google-opensource.blogspot.com/2008/11/gerrit-and-repo-android-source.html">Gerrit and Repo, the Android Source Management Tools</a></strong> &#8211; Google has built some tools to make git work better for large-scale projects, including workflow and code-review bits.</li>
<li><strong><a href="http://www.jetbrains.com/ruby/index.html">RubyMine Public Preview</a></strong> &#8211; JetBrains is getting into the Rails IDE business. I may take a look, though honestly, two years after closing the IDE I don&#8217;t miss it.</li>
<li><strong><a href="http://github.com/blog/202-github-code-search">GitHub Code Search</a></strong> &#8211; A bit of poking around here reveals that Ruby coders pretty much have a lock on the chunky bacon market.</li>
<li><strong><a href="http://merb.4ninjas.org/">Life on the Edge with Merb, DataMapper, and RSpec</a></strong> &#8211; Work-in-progress aimed for folks who might be thinking of switching from Rails.</li>
<li><strong><a href="http://m.onkey.org/2008/11/3/activesupport-rescuable">ActiveSupport::Rescuable</a></strong> &#8211; Pratik Naik shows how to mix this into your own code with Rails 2.2.</li>
<li><strong><a href="http://sixrevisions.com/resources/40-beautiful-free-icon-sets/">40 Beautiful Free Icon Sets</a></strong> &#8211; Some nice stuff out there; be sure to check the fine print before using.</li>
</ul>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[RDoc can let you down, can give you up, can run around and desert you...]]></title>
<link>http://houseofpostmodern.wordpress.com/2008/10/24/rdoc-can-let-you-down-can-give-you-up/</link>
<pubDate>Fri, 24 Oct 2008 07:00:02 +0000</pubDate>
<dc:creator>postmodern3</dc:creator>
<guid>http://houseofpostmodern.wordpress.com/2008/10/24/rdoc-can-let-you-down-can-give-you-up/</guid>
<description><![CDATA[Normally RDoc is there for you when it comes to auto-generating nice HTML documentation for your Rub]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Normally <a href="http://rdoc.sourceforge.net/">RDoc</a> is there for you when it comes to auto-generating nice HTML documentation for your Ruby projects. But just now, it flat out failed while generating <a href="http://www.graphviz.org/">Graphviz</a> diagrams of my code.</p>
<p>I was attempting to generate some documentation for the <a href="http://github.com/postmodern/ronin-sql/tree/dsl_refactor">Ronin SQL library</a> in order to test the formatting of README.txt. To my surprise <code>rake docs</code> failed without any informative error message describing which file caused RDoc to chock.</p>
<p>Here&#8217;s the output of <code>rake --trace docs</code>:</p>
<p>[ <a href="http://gist.github.com/19353">gist.github.com/19353</a> ]<code><br />
Generating HTML...<br />
Diagrams: ...<br />
/usr/lib64/ruby/1.8/rdoc/markup/simple_markup/fragments.rb:291: warning: Object#type is deprecated; use Object#class<br />
rake aborted!<br />
undefined method `level' for nil:NilClass<br />
/usr/lib64/ruby/1.8/rdoc/markup/simple_markup/fragments.rb:292:in `add_list_breaks'<br />
/usr/lib64/ruby/1.8/rdoc/markup/simple_markup/fragments.rb:282:in `each'<br />
/usr/lib64/ruby/1.8/rdoc/markup/simple_markup/fragments.rb:282:in `add_list_breaks'<br />
/usr/lib64/ruby/1.8/rdoc/markup/simple_markup/fragments.rb:153:in `normalize'<br />
/usr/lib64/ruby/1.8/rdoc/markup/simple_markup.rb:459:in `group_lines'<br />
/usr/lib64/ruby/1.8/rdoc/markup/simple_markup.rb:255:in `convert'<br />
/usr/lib64/ruby/1.8/rdoc/generators/html_generator.rb:246:in `markup'<br />
/usr/lib64/ruby/1.8/rdoc/generators/html_generator.rb:818:in `value_hash'<br />
/usr/lib64/ruby/1.8/rdoc/generators/html_generator.rb:865:in `write_on'<br />
/usr/lib64/ruby/1.8/rdoc/generators/html_generator.rb:1293:in `gen_into'<br />
/usr/lib64/ruby/1.8/rdoc/generators/html_generator.rb:1293:in `open'<br />
/usr/lib64/ruby/1.8/rdoc/generators/html_generator.rb:1293:in `gen_into'<br />
/usr/lib64/ruby/1.8/rdoc/generators/html_generator.rb:1289:in `each'<br />
/usr/lib64/ruby/1.8/rdoc/generators/html_generator.rb:1289:in `gen_into'<br />
/usr/lib64/ruby/1.8/rdoc/generators/html_generator.rb:1276:in `generate_html'<br />
/usr/lib64/ruby/1.8/rdoc/generators/html_generator.rb:1197:in `generate'<br />
/usr/lib64/ruby/1.8/rdoc/rdoc.rb:284:in `document'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake/rdoctask.rb:113:in `define'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:617:in `call'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:617:in `execute'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:612:in `each'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:612:in `execute'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:578:in `invoke_with_call_chain'<br />
/usr/lib64/ruby/1.8/monitor.rb:242:in `synchronize'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:571:in `invoke_with_call_chain'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:588:in `invoke_prerequisites'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:585:in `each'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:585:in `invoke_prerequisites'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:577:in `invoke_with_call_chain'<br />
/usr/lib64/ruby/1.8/monitor.rb:242:in `synchronize'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:571:in `invoke_with_call_chain'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:564:in `invoke'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:2019:in `invoke_task'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1997:in `top_level'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1997:in `each'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1997:in `top_level'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:2036:in `standard_exception_handling'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1991:in `top_level'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1970:in `run'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:2036:in `standard_exception_handling'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1967:in `run'<br />
/usr/lib64/ruby/gems/1.8/gems/rake-0.8.3/bin/rake:31<br />
/usr/bin/rake:19:in `load'<br />
/usr/bin/rake:19<br />
</code></p>
<p>Suddenly, all that talk about <a href="http://www.infoq.com/news/2008/07/yard-documentation-generator">YARD</a> replacing RDoc is sounding a lot more pragmatic. YARD has certainly worked out for <a href="http://datamapper.rubyforge.org/">DataMapper</a> and <a href="http://merbivore.com/documentation.html">Merb</a> thus far. Maybe <a href="http://ronin.rubyforge.org/">Ronin</a> will give <a href="http://yard.rubyforge.org/">YARD</a> a try.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Introducing Ronin, a hacking environment for the rest of us]]></title>
<link>http://houseofpostmodern.wordpress.com/2008/09/24/introducing-ronin-009/</link>
<pubDate>Wed, 24 Sep 2008 00:03:23 +0000</pubDate>
<dc:creator>postmodern3</dc:creator>
<guid>http://houseofpostmodern.wordpress.com/2008/09/24/introducing-ronin-009/</guid>
<description><![CDATA[Ronin has been my main quasi-secret (I only told people who asked what I was hacking on in GVim) pro]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><a href="http://ronin.rubyforge.org/">Ronin</a> has been my main quasi-secret (I only told people who asked what I was hacking on in GVim) project for some time now. It has also been driving most of my side projects, such as <a href="http://gscraper.rubyforge.org/">GScraper</a>, <a href="http://reverserequire.rubyforge.org/">reverse-require</a> and <a href="http://repertoire.rubyforge.org/">R&#8217;epertoire</a>. The code-base has finally settled down now, allowing me to release version <a href="http://rubyforge.org/frs/?group_id=3798&#38;release_id=25020">0.0.9</a> of <a href="http://ronin.rubyforge.org/">Ronin</a>. This is an initial beta-release, so not all of the desired features are present, although I&#8217;m always <a href="http://rubyforge.org/forum/?group_id=3798">looking</a> for <a href="http://rubyforge.org/tracker/?atid=14633&#38;group_id=3798&#38;func=browse">user-feedback</a>.</p>
<p><a href="http://ronin.rubyforge.org/">Ronin</a> is a platform for information security and data-exploration tasks. Ronin harnesses the elegance of Ruby (one-liner convenience methods, sparse <a href="http://en.wikipedia.org/wiki/Monkey_patch">monkey-patching</a>, <a href="http://en.wikipedia.org/wiki/Meta_programming">meta-programming</a>, <a href="http://pragdave.blogs.pragprog.com/pragdave/2008/03/the-language-in.html">Domain Specific Languages</a> (DSL) and <a href="http://en.wikipedia.org/wiki/Duck_typing">duck-typing</a>) to provide the user with a robust API, an extendable command-line utility and a customized <a href="http://en.wikipedia.org/wiki/IRB">IRB</a> console.</p>
<p><a href="http://ronin.rubyforge.org/">Ronin</a> is considered a platform and not a framework, since it has the ability to install Overlays of code (think extensions) and data (think exploit/shellcode repositories) from any <a href="http://subversion.tigris.org/">SubVersion</a> (SVN), <a href="http://git.or.cz/">Git</a>, <a href="http://www.nongnu.org/cvs/">CVS</a> or <a href="http://samba.anu.edu.au/rsync/">Rsync</a> repositories, which are then integrated into Ronin&#8217;s environment. The ability to install 3rd party code or data from any common source-code repository using just a URI is what makes Ronin decentralized.</p>
<p><a href="http://ronin.rubyforge.org/">Ronin</a> is not bloated either, most of it&#8217;s functionality is divided between various libraries which can be selectively installed by the user. These libraries allow the user to choose what functionality they need from Ronin. Ronin currently provides the following libraries:</p>
<ul>
<li><a href="http://ronin.rubyforge.org/docs/ronin-sql/">Ronin SQL</a> &#8211; Provides <a href="http://unixwiz.net/techtips/sql-injection.html">SQL Injection</a> tests, exploitation methods and a DSL for generating <a href="http://ha.ckers.org/sqlinjection/">complex</a> SQL Injection statements.</li>
<li><a href="http://ronin.rubyforge.org/docs/ronin-php/">Ronin PHP</a> &#8211; Provides PHP Local File Inclusion (LFI) and <a href="http://en.wikipedia.org/wiki/Remote_File_Inclusion">Remote File Inclusion</a> (RFI) tests, fingerprinting, exploitation methods and a custom PHP Remote Procedure Call (RPC) server which can injected via RFI vulnerabilities.</li>
<li><a href="http://ronin.rubyforge.org/docs/ronin-dorks/">Ronin Dorks</a> &#8211; Provides a simply API for performing common or even custom <a href="http://www.encription.co.uk/downloads/The_Google_Hackers_Guide_v1.0.pdf">Google Dorks</a>.</li>
<li><a href="http://ronin.rubyforge.org/docs/ronin-exploits/">Ronin Exploits</a> &#8211; Provides an API for defining <a href="http://milw0rm.com/">Exploits or Payloads</a> which can also be distributed over the previously mentioned Overlays and cached by Ronin for later use.</li>
</ul>
<p><a href="http://ronin.rubyforge.org/">Ronin</a> is packaged as a RubyGem and can be downloaded <a href="http://rubyforge.org/frs/?group_id=3798&#38;release_id=25020">here</a>. To install Ronin using RubyGems, simply run the following command:</p>
<pre>$ sudo gem install ronin</pre>
<p>Documentation for <a href="http://ronin.rubyforge.org/">Ronin</a> and it&#8217;s libraries can be found <a href="http://ronin.rubyforge.org/docs/">here</a>. If you have further questions there&#8217;s also a <a href="http://ronin.rubyforge.org/faq.html">FAQ</a> for Ronin.</p>
<p><strong>Update 2:</strong> I have recently published a <a href="http://ronin.rubyforge.org/resources/everyday_ronin.html">HOWTO</a> covering Ronin&#8217;s convenience methods and how to perform everyday tasks in the Ronin Console (such as owning web-servers).</p>
<p><strong>Update 1:</strong> An astute reader of this blog pointed out that R&#8217;epertoire 0.1.2, which is required by Ronin, was not yet released as a RubyGem on rubyforge.org. This issue has been corrected and R&#8217;epertoire 0.1.2 is now available for <a href="http://rubyforge.org/frs/?group_id=5272&#38;release_id=26451">download</a>.</p>
<p>Also expect a release of the <a href="http://ronin.rubyforge.org/docs/ronin-exploits/">Ronin Exploits</a> soon (I&#8217;m in the process of adding the beginnings of <a href="http://seattle.toorcon.org/2007/talks.php?id=11">Vulnerability Taxonomy</a> to the <a href="http://ronin.rubyforge.org/docs/ronin-exploits/Ronin/Exploits/Exploit.html">Exploit</a> base-class).</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Ruby and JRuby JSON Time with json, json_pure, and Merb + DataMapper extlib]]></title>
<link>http://blog.idearise.com/2008/09/12/ruby-and-jruby-json-time-with-json-json_pure-and-merb-datamapper-extlib/</link>
<pubDate>Fri, 12 Sep 2008 21:52:17 +0000</pubDate>
<dc:creator>robertor</dc:creator>
<guid>http://blog.idearise.com/2008/09/12/ruby-and-jruby-json-time-with-json-json_pure-and-merb-datamapper-extlib/</guid>
<description><![CDATA[After trying to run a super-simple Ruby script in JRuby that ran fine through the MRI, I found mysel]]></description>
<content:encoded><![CDATA[After trying to run a super-simple Ruby script in JRuby that ran fine through the MRI, I found mysel]]></content:encoded>
</item>
<item>
<title><![CDATA[merb 0.9.5 + haml + datamapper + sqlite3]]></title>
<link>http://blog.idearise.com/2008/09/04/merb-095-haml-datamapper-sqlite3/</link>
<pubDate>Thu, 04 Sep 2008 18:31:31 +0000</pubDate>
<dc:creator>robertor</dc:creator>
<guid>http://blog.idearise.com/2008/09/04/merb-095-haml-datamapper-sqlite3/</guid>
<description><![CDATA[Since Merb is constantly changing prior to its 1.0 release, a lot of the tutorials did not work exac]]></description>
<content:encoded><![CDATA[Since Merb is constantly changing prior to its 1.0 release, a lot of the tutorials did not work exac]]></content:encoded>
</item>
<item>
<title><![CDATA[Installing DataMapper and Merb without using sudo]]></title>
<link>http://onruby.wordpress.com/2008/08/10/installing-datamapper-and-merb-without-using-sudo/</link>
<pubDate>Sun, 10 Aug 2008 13:22:58 +0000</pubDate>
<dc:creator>Jan Kubr</dc:creator>
<guid>http://onruby.wordpress.com/2008/08/10/installing-datamapper-and-merb-without-using-sudo/</guid>
<description><![CDATA[DataMapper (dm-core, dm-more): rake install SUDOLESS=true Merb (merb-core, merb-more, merb-plugins):]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><strong>DataMapper (dm-core, dm-more)</strong>:</p>
<pre>rake install SUDOLESS=true</pre>
<p><strong>Merb (merb-core, merb-more, merb-plugins)</strong>:</p>
<pre>rake install MERB_SUDO=</pre>
<p>oh, well.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Ruby,Rubinius,IronRuby,Rails and Merb Group on FaceBook]]></title>
<link>http://rubyworld.wordpress.com/2008/07/05/rubyrubiniusironrubyrails-and-merb-group-on-facebook/</link>
<pubDate>Sat, 05 Jul 2008 08:40:40 +0000</pubDate>
<dc:creator>SoftMind</dc:creator>
<guid>http://rubyworld.wordpress.com/2008/07/05/rubyrubiniusironrubyrails-and-merb-group-on-facebook/</guid>
<description><![CDATA[Hello, I just came across a new group created on FaceBook, which covers major subjects like&#8230; (]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Hello,</p>
<p>I just came across a new group created on FaceBook, which covers major subjects like&#8230; (1) Ruby (2) Rubinius (3) IronRuby (4) Rails and (5) Merb.</p>
<p>The main goal is to discuss all this major topics under on roof. This group is specially created by Indian developers, with a mission to promote Rails and other related languages/frameworks in India.</p>
<p>I would highly recommend joining there.</p>
<p>Thanks</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[require 'activerecord']]></title>
<link>http://tecnogemas.wordpress.com/2008/04/21/require-activerecord/</link>
<pubDate>Mon, 21 Apr 2008 17:12:16 +0000</pubDate>
<dc:creator>eipipuz</dc:creator>
<guid>http://tecnogemas.wordpress.com/2008/04/21/require-activerecord/</guid>
<description><![CDATA[Hoy nos subimos al vagón de los ORMs. Debo de confesarles dos cosas: 1. no soy muy fan de las bases ]]></description>
<content:encoded><![CDATA[Hoy nos subimos al vagón de los ORMs. Debo de confesarles dos cosas: 1. no soy muy fan de las bases ]]></content:encoded>
</item>

</channel>
</rss>
