<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" gd:etag="W/&quot;CEUBSXs5fip7ImA9WhBaE0g.&quot;"><id>tag:blogger.com,1999:blog-3483689298596906177</id><updated>2013-05-24T01:37:38.526+02:00</updated><category term="ruby" /><category term="bugfix" /><category term="rspec" /><category term="i18n" /><category term="unitrecord" /><category term="web2.0" /><category term="documental database" /><category term="mongo" /><category term="cms" /><category term="gem" /><category term="php" /><category term="cmf" /><category term="books" /><category term="rails" /><category term="programming" /><category term="mongoid" /><category term="tdd" /><category term="testing" /><category term="bdd" /><category term="learning" /><category term="inspiration" /><category term="mongodb" /><title>Codecaster</title><subtitle type="html">n.times { code! }</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.codecaster.es/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.codecaster.es/" /><author><name>Papipo</name><uri>http://www.blogger.com/profile/10673361479709852302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://bp1.blogger.com/_ndEy9wFW2e8/SIxh0W6yXKI/AAAAAAAAAAU/pQajPQ4FK4w/S220/mypictr_last.fm.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/papipo" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="papipo" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>43.52658422854318</geo:lat><geo:long>-5.680661201477051</geo:long><entry gd:etag="W/&quot;CUUBRX05eip7ImA9WxFUFUs.&quot;"><id>tag:blogger.com,1999:blog-3483689298596906177.post-6930874328827732873</id><published>2010-05-03T01:19:00.004+02:00</published><updated>2010-06-26T16:40:54.322+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-26T16:40:54.322+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="mongoid" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="i18n" /><category scheme="http://www.blogger.com/atom/ns#" term="mongodb" /><category scheme="http://www.blogger.com/atom/ns#" term="gem" /><title>i18n gem for mongoid</title><content type="html">I have just released my first gem!&lt;br /&gt;&lt;br /&gt;It tries to leverage the pain in the ass that is model localization. It's for mongoid in this case, and its a pleasure to use (supposing that it works fine, since it hasn't been tested in a real environment yet).&lt;br /&gt;&lt;br /&gt;I won't bother you with the details, since you can &lt;a href="http://github.com/Papipo/mongoid_i18n"&gt;see a readme&lt;/a&gt; or even check the kind of &lt;a href="http://groups.google.com/group/mongoid/browse_thread/thread/f855be72ac6e2b1b"&gt;announcement I made in the mongoid google group&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you apps uses mongoid and you need to localize your fields, please check it out and test as much as you can. I need feedback to fix broken stuff and add new features.&lt;img src="http://feeds.feedburner.com/~r/papipo/~4/Q3vxlH3ivB4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.codecaster.es/feeds/6930874328827732873/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3483689298596906177&amp;postID=6930874328827732873" title="14 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/6930874328827732873?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/6930874328827732873?v=2" /><link rel="alternate" type="text/html" href="http://blog.codecaster.es/2010/05/i18n-gem-for-mongoid.html" title="i18n gem for mongoid" /><author><name>Papipo</name><uri>http://www.blogger.com/profile/10673361479709852302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://bp1.blogger.com/_ndEy9wFW2e8/SIxh0W6yXKI/AAAAAAAAAAU/pQajPQ4FK4w/S220/mypictr_last.fm.jpg" /></author><thr:total>14</thr:total></entry><entry gd:etag="W/&quot;CE8AR3k8fCp7ImA9WxBaEUw.&quot;"><id>tag:blogger.com,1999:blog-3483689298596906177.post-853100158066697938</id><published>2010-03-20T19:35:00.005+01:00</published><updated>2010-03-20T20:20:46.774+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-20T20:20:46.774+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><category scheme="http://www.blogger.com/atom/ns#" term="books" /><category scheme="http://www.blogger.com/atom/ns#" term="inspiration" /><title>Start anew</title><content type="html">I have just lost my job.&lt;br /&gt;&lt;br /&gt;A lot of people collapse because of this very same reason. Maybe it has something to do with times of crisis, I don't know. I see this as an opportunity to explore new ways of working, try my very own ideas, and invest time in research, reading and learning in general.&lt;br /&gt;&lt;br /&gt;In Spain you can request part of the unemployment benefit as an unique payment if you are going to be either entrepreneur or self-employed. The latter is my case.&lt;br /&gt;&lt;br /&gt;This money can only be spent as an investment for your new endeavour. I requested it, and I will update my computer to a brand new iMac quadcore, and that's pretty fine. I will even buy a new and ergonomic chair, but that's not the point of this entry.&lt;br /&gt;&lt;br /&gt;I bought books. "How many?", you might think. Well... I bought 78.&lt;br /&gt;&lt;br /&gt;I bought 78 books at amazon.co.uk, mainly technical ones, some about project management or productivity. Web design is present as well, as is Javascript, Erlang, Lua, Blender or iPhone development, among others. The bulk are C++ and game development books. That's because I want to design and develop games, or at least I want to try. And I know that I am good at trying.&lt;br /&gt;&lt;br /&gt;So far in my life, I have learned how to program in several languages, doing magic tricks, dancing popping, playing the guitar and lately I started playing the piano. I am self-taught, as many developers are, but I self teach me in many, many areas as you can see. I don't even know where my knowledge about the English language comes from. I think that I taught that to myself too.&lt;br /&gt;&lt;br /&gt;It's all about attitude and will. If you think... no, I'll rephrase that: If you &lt;span style="font-weight:bold;"&gt;know&lt;/span&gt; that you can do it, you will be able to do it. It takes some time to get to this point, though. Even I have some breakdowns and I think that I won't be able to do or learn something. But I end up being able to do it. Always. It's about perseverance and self-confidence. The good thing about this, is that when you become proficient at learning by yourself, it becomes second nature. Well, kind of.&lt;br /&gt;&lt;br /&gt;I already read one of the books, it's &lt;a href="http://www.pragprog.com/titles/ahptl/pragmatic-thinking-and-learning"&gt;Pragmatic Thinking and Learning: Refactor Your Wetware&lt;/a&gt;. I really liked it, it has lots of interesting ideas that I am eager to try. But one of the interesting things I noted was that I already apply some of the practices that Andy recommends on his book. And I think that somehow they just came out of the blue, because of my bias towards embracing change and learning new things.&lt;br /&gt;&lt;br /&gt;I don't know if I am going to blog more often, but I should, and I think I will. It would be nice to use my blog as a real log of the changes to come. I think that I should rename it to Papipo 3.0, though.&lt;img src="http://feeds.feedburner.com/~r/papipo/~4/n_SybHQ0dMQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.codecaster.es/feeds/853100158066697938/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3483689298596906177&amp;postID=853100158066697938" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/853100158066697938?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/853100158066697938?v=2" /><link rel="alternate" type="text/html" href="http://blog.codecaster.es/2010/03/start-anew.html" title="Start anew" /><author><name>Papipo</name><uri>http://www.blogger.com/profile/10673361479709852302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://bp1.blogger.com/_ndEy9wFW2e8/SIxh0W6yXKI/AAAAAAAAAAU/pQajPQ4FK4w/S220/mypictr_last.fm.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkAMQX85fSp7ImA9WxBTEkQ.&quot;"><id>tag:blogger.com,1999:blog-3483689298596906177.post-6202440079586047326</id><published>2009-09-25T16:58:00.006+02:00</published><updated>2009-12-08T18:53:00.125+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-08T18:53:00.125+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="documental database" /><category scheme="http://www.blogger.com/atom/ns#" term="cmf" /><category scheme="http://www.blogger.com/atom/ns#" term="cms" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="mongo" /><category scheme="http://www.blogger.com/atom/ns#" term="mongodb" /><title>Congo-cms, a content management framework in rails and mongodb</title><content type="html">I've started &lt;a href="http://github.com/Papipo/congo-cms"&gt;a project in github&lt;/a&gt;, which is a prototype of something that I've been searching for years: a flexible content management system/framework that makes sense.&lt;br /&gt;&lt;br /&gt;I've looked into ez publish and similar stuff, recently I've met expression engine, and I have even considered the drupal model. What all these systems have in common is one --in my opinion-- bad constraint: they store their data in a relational database.&lt;br /&gt;&lt;br /&gt;Those CMS or CMF basically "simulate" a documental database on top of a relational one. I can't see how that can be good.&lt;br /&gt;&lt;br /&gt;My aim with congo-cms (a name which comes from content+mongo -- yeah, I know, pretty smart name xD) is to offer a framework to define flexible datatypes, as ez publish and its companions do, but with the actual data stored in the proper way. If you create a blog using congo-cms, the blog post documents stored in mongodb, won't differ from those that you could store if the application was a plain weblog made with rails as in the old fashion.&lt;br /&gt;&lt;br /&gt;I'm using MongoMapper mainly because it really fits my idea of using embedded datatypes. For example a User could have Addresses, and those should be stored in the User document itself. With MongoMapper this feature comes straight out of the box.&lt;br /&gt;&lt;br /&gt;I hope to improve development a bit in the next weeks, and hopefully we will use something similar in my company's next project.&lt;img src="http://feeds.feedburner.com/~r/papipo/~4/iyN48Vk9Fxc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.codecaster.es/feeds/6202440079586047326/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3483689298596906177&amp;postID=6202440079586047326" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/6202440079586047326?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/6202440079586047326?v=2" /><link rel="alternate" type="text/html" href="http://blog.codecaster.es/2009/09/congo-content-management-framework-in.html" title="Congo-cms, a content management framework in rails and mongodb" /><author><name>Papipo</name><uri>http://www.blogger.com/profile/10673361479709852302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://bp1.blogger.com/_ndEy9wFW2e8/SIxh0W6yXKI/AAAAAAAAAAU/pQajPQ4FK4w/S220/mypictr_last.fm.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkAMQ346eyp7ImA9WxVWF0k.&quot;"><id>tag:blogger.com,1999:blog-3483689298596906177.post-5675324900923638936</id><published>2009-02-27T14:01:00.006+01:00</published><updated>2009-02-27T15:26:22.013+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-27T15:26:22.013+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tdd" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><title>unit vs. functional tests</title><content type="html">&lt;span style="font-family:trebuchet ms;"&gt;Sometimes I find myself thinking about unit tests being useless. Not that really useless, but bothering, at least when compared to functional tests.&lt;br /&gt;&lt;br /&gt;In the end, you should really rely on functional tests to check the health of your application, since those are the only tests that are really checking that all your stack works perfectly, top to bottom, that the database schema is ok, and that permissions and data are handled correctly.&lt;br /&gt;&lt;br /&gt;You can even add functional tests to an existing (legacy?) system to use them as regression tests, and to be able to refactor parts of the application while knowing that everything is still right, while adding unit tests could be a pain in the ass, and not that useful, really.&lt;br /&gt;&lt;br /&gt;Why are unit tests bothering? They are harder to maintain. You usually can change the implementation of some functionality without touching functionals, but you usually have to make changes to your unit tests. I recommend you to abuse stubs to keep the coupling to a minimum, though.&lt;br /&gt;&lt;br /&gt;Anyway, when it al comes down to the development itself, it's when unit tests really shine. They allow you to start coding any class without worrying about other classes, thanks to mocks and stubs. They help you to think about communication between your objects or processes or whatever, because you should create your methods or functions simple enough that they can be easily tested. And finally, they are your api documentation. They allow any other developer to learn your application by example.&lt;br /&gt;&lt;/span&gt;&lt;img src="http://feeds.feedburner.com/~r/papipo/~4/fc_ipxnoMcs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.codecaster.es/feeds/5675324900923638936/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3483689298596906177&amp;postID=5675324900923638936" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/5675324900923638936?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/5675324900923638936?v=2" /><link rel="alternate" type="text/html" href="http://blog.codecaster.es/2009/02/unit-vs-functional-tests.html" title="unit vs. functional tests" /><author><name>Papipo</name><uri>http://www.blogger.com/profile/10673361479709852302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://bp1.blogger.com/_ndEy9wFW2e8/SIxh0W6yXKI/AAAAAAAAAAU/pQajPQ4FK4w/S220/mypictr_last.fm.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUQHQHk_fCp7ImA9WB9UEEw.&quot;"><id>tag:blogger.com,1999:blog-3483689298596906177.post-4922455645443834793</id><published>2007-12-07T09:45:00.000+01:00</published><updated>2007-12-07T09:48:51.744+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-07T09:48:51.744+01:00</app:edited><title>Rails 2.0 released</title><content type="html">Although there is no info about this in the &lt;a href="http://blog.rubyonrails.com/"&gt;rails blog&lt;/a&gt;, I did a gem update this morning, anv voilà:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;papipo$ sudo gem update&lt;br /&gt;Updating installed gems...&lt;br /&gt;Bulk updating Gem source index for: http://gems.rubyforge.org&lt;br /&gt;Attempting remote update of actionmailer&lt;br /&gt;Install required dependency actionpack? [Yn]&lt;br /&gt;Install required dependency activesupport? [Yn]&lt;br /&gt;Successfully installed actionmailer-2.0.0&lt;br /&gt;Successfully installed actionpack-2.0.0&lt;br /&gt;Successfully installed activesupport-2.0.0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And it keeps going with all 2.0 libs.&lt;br /&gt;&lt;br /&gt;Greetings for the rails team.&lt;br /&gt;&lt;br /&gt;Enjoy 2.0.&lt;img src="http://feeds.feedburner.com/~r/papipo/~4/o8GfR6UwoGU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.codecaster.es/feeds/4922455645443834793/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3483689298596906177&amp;postID=4922455645443834793" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/4922455645443834793?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/4922455645443834793?v=2" /><link rel="alternate" type="text/html" href="http://blog.codecaster.es/2007/12/rails-20-released.html" title="Rails 2.0 released" /><author><name>Papipo</name><uri>http://www.blogger.com/profile/10673361479709852302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://bp1.blogger.com/_ndEy9wFW2e8/SIxh0W6yXKI/AAAAAAAAAAU/pQajPQ4FK4w/S220/mypictr_last.fm.jpg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;D0QEQXw8eCp7ImA9WB9REUw.&quot;"><id>tag:blogger.com,1999:blog-3483689298596906177.post-5476734419874058939</id><published>2007-10-11T16:48:00.000+02:00</published><updated>2007-10-11T17:08:20.270+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-10-11T17:08:20.270+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="tdd" /><category scheme="http://www.blogger.com/atom/ns#" term="unitrecord" /><category scheme="http://www.blogger.com/atom/ns#" term="bugfix" /><title>UnitRecord and rails 2.0 PR</title><content type="html">I've been reading about &lt;a href="http://blog.jayfields.com/2007/09/rails-how-we-test.html"&gt;another way of testing&lt;/a&gt;, and I thought that I should give it a try.&lt;br /&gt;The problem is that when you setup all the needed steps, &lt;a href="http://unit-test-ar.rubyforge.org/"&gt;UnitRecord&lt;/a&gt; complains about ActiveRecord trying to connect to the database:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[...]&lt;br /&gt;RuntimeError: ActiveRecord is disconnected; database access is unavailable in unit tests.&lt;br /&gt;[...]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is due to some changes in rails trunk, that added a "reset_cache" method that checks for an ActiveRecord connection.&lt;br /&gt;&lt;br /&gt;In order to avoid this, you can change your &lt;strong&gt;unit_test_helper.rb&lt;/strong&gt; from this (as shown in &lt;a href="http://unit-test-ar.rubyforge.org/"&gt;UnitRecord documentation&lt;/a&gt;):&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;require File.dirname(__FILE__) + "/../test_helper"&lt;br /&gt;require "unit_record"&lt;br /&gt;ActiveRecord::Base.disconnect!&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;to this:&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;require File.dirname(__FILE__) + '/../test_helper.rb'&lt;br /&gt;require 'unit_record'&lt;br /&gt;&lt;br /&gt;module UnitRecord&lt;br /&gt;  module DisconnectedFixtures&lt;br /&gt;    def disconnect!&lt;br /&gt;      (class &lt;&lt; self; self; end).class_eval do&lt;br /&gt;        def create_fixtures(*args); end&lt;br /&gt;        def reset_cache(*args); end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;ActiveRecord::Base.disconnect!&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That will take care of errors.&lt;br /&gt;Happy testing!&lt;img src="http://feeds.feedburner.com/~r/papipo/~4/o-4TTtlOKNo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.codecaster.es/feeds/5476734419874058939/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3483689298596906177&amp;postID=5476734419874058939" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/5476734419874058939?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/5476734419874058939?v=2" /><link rel="alternate" type="text/html" href="http://blog.codecaster.es/2007/10/unitrecord-and-rails-20-pr.html" title="UnitRecord and rails 2.0 PR" /><author><name>Papipo</name><uri>http://www.blogger.com/profile/10673361479709852302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://bp1.blogger.com/_ndEy9wFW2e8/SIxh0W6yXKI/AAAAAAAAAAU/pQajPQ4FK4w/S220/mypictr_last.fm.jpg" /></author><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;DEAAQ3gyfSp7ImA9WB5bF0o.&quot;"><id>tag:blogger.com,1999:blog-3483689298596906177.post-8946144584520595518</id><published>2007-08-30T11:17:00.000+02:00</published><updated>2007-09-03T01:45:42.695+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-09-03T01:45:42.695+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="rspec" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="bdd" /><title>BDD, isolation, integration</title><content type="html">I have been reading a lot of posts about &lt;a href="http://therailsway.com/2007/6/1/railsconf-recap-skinny-controllers"&gt;skinny&lt;/a&gt; &lt;a href="http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model"&gt;controllers&lt;/a&gt;, isolation and good &lt;a href="http://opensoul.org/2007/6/20/rspec-is-getting-too-intimate-with-my-code"&gt;behaviour-driven development&lt;/a&gt;. Let me explain from the beginning:&lt;br /&gt;&lt;br /&gt;The typical approach to spec a 'create' action looks like this (Taken from rspec documentation):&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;describe PeopleController do&lt;br /&gt;  it "with a valid person should redirect to index on successful POST to create" do&lt;br /&gt;    @person.should_receive(:new_record?).and_return(false)&lt;br /&gt;    Person.should_receive(:create).with({"name" =&gt; 'Aslak'}).and_return(@person)&lt;br /&gt;&lt;br /&gt;    post 'create', {:person =&gt; {:name =&gt; 'Aslak'}}&lt;br /&gt;&lt;br /&gt;    response.should redirect_to(:action =&gt; 'index')&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That is &lt;span style="font-weight: bold;"&gt;too tied to the implementation&lt;/span&gt;. What if I want to use the 'create' method in my controller? And what about assigning attributes in a block?&lt;br /&gt;What you are spec-ing here, is how your controller should &lt;span style="font-weight: bold;"&gt;look&lt;/span&gt;, not how it should &lt;span style="font-weight: bold;"&gt;behave&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Then I saw this in one of the blogs that I linked above:&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;it "should create a new thing" do&lt;br /&gt;  lambda { do_post }.should change { Thing.count }.by(1)&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is really testing behaviour. The main problem with this (although I really liked it the first time I saw it) is, of course, that interacts with the database and the models. I don't want to hit the database from my controller specs at all, I want &lt;span style="font-weight: bold;"&gt;full isolation&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Add a pair of helpers in spec_helper.rb:&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;def mock_valid_model(klass)&lt;br /&gt;  mock_model(klass, :save =&gt; true, :save! =&gt; true)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def mock_invalid_model(klass)&lt;br /&gt;  m = mock_model(klass, :save =&gt; false)&lt;br /&gt;  m.stub!(:save!).and_raise(ActiveRecord::RecordNotSaved)&lt;br /&gt;  m&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then stub Model.new to return the mock you want. Spec your controller 'create' action in order to redirect in case that the mock is valid, and to render a template if it is not valid (of course you can add specs for flash or whatever):&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="ruby"&gt;&lt;br /&gt;describe ThingsController, '"create" a valid model by POST' do&lt;br /&gt;  before do&lt;br /&gt;    @thing = mock_valid_model(Thing)&lt;br /&gt;    Thing.stub!(:new).and_return(@thing)&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  it 'should redirect to model show' do&lt;br /&gt;    post :create&lt;br /&gt;    response.should redirect_to(thing_url(@thing))&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;describe ThingsController, '"create" an invalid model by POST' do&lt;br /&gt;  before do&lt;br /&gt;    @thing = mock_invalid_model(Thing)&lt;br /&gt;    Thing.stub!(:new).and_return(@thing)&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  it 'should render "create" template' do&lt;br /&gt;    post :create&lt;br /&gt;    response.should render_template('things/create')&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There are various interesting things here:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;You don't need to keep adding expectations to your mocks. &lt;span style="font-weight: bold;"&gt;Expectations couple your specs with the implementation&lt;/span&gt;. With my approach you can use create, new + save, new + block assignement, whatever. And &lt;span style="font-weight: bold;"&gt;the spec still passes&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;The database isn't touched at all. That's good stuff, I guess.&lt;/li&gt;&lt;li&gt;You are really &lt;span style="font-weight: bold;"&gt;testing the behaviour&lt;/span&gt;. You know that the only way your controller will know if it should redirect or render, is to create a new instance of Thing, and call save or save!. That is actually an &lt;span style="font-weight: bold;"&gt;implied expectation&lt;/span&gt;, but without the need of should_receive(), just stubs.&lt;/li&gt;&lt;/ol&gt;Some of you may have noticed that I don't need to use the params() hash in the controller in order to make the specs pass. Right. But you know, that your controller is creating a new instance of Thing, and calling save, save!, create or whatever. That's when &lt;span style="font-weight: bold;"&gt;integration/acceptance&lt;/span&gt; tests come in&lt;br /&gt;&lt;br /&gt;The only moment that you want your controller mess with params, is when you are not isolating. Because, &lt;span style="font-weight: bold;"&gt;if you are isolating, you can't validate parameters&lt;/span&gt;, since you stubbed save and save!.&lt;br /&gt;&lt;br /&gt;With this approach, you keep your specs to a minimum amount of lines, you isolate, you test just behaviour.&lt;br /&gt;&lt;br /&gt;Anyway, let me know of any issues you find with this.&lt;br /&gt;&lt;br /&gt;Thanks for reading and sorry about the syntax non-highlighting.&lt;img src="http://feeds.feedburner.com/~r/papipo/~4/X5MVBd6oIBk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.codecaster.es/feeds/8946144584520595518/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3483689298596906177&amp;postID=8946144584520595518" title="20 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/8946144584520595518?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/8946144584520595518?v=2" /><link rel="alternate" type="text/html" href="http://blog.codecaster.es/2007/08/bdd-isolation-integration.html" title="BDD, isolation, integration" /><author><name>Papipo</name><uri>http://www.blogger.com/profile/10673361479709852302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://bp1.blogger.com/_ndEy9wFW2e8/SIxh0W6yXKI/AAAAAAAAAAU/pQajPQ4FK4w/S220/mypictr_last.fm.jpg" /></author><thr:total>20</thr:total></entry><entry gd:etag="W/&quot;Ak4DRn4_cCp7ImA9WB5bFEo.&quot;"><id>tag:blogger.com,1999:blog-3483689298596906177.post-497604632708441373</id><published>2006-10-11T16:58:00.000+02:00</published><updated>2007-08-30T15:02:57.048+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-08-30T15:02:57.048+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="web2.0" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="php" /><title>Killer App (Hopefully)</title><content type="html">We are developing a web publishing tool at my company. We hope that it will create a huge community of designers that don't want to mess with php|java|*any* code. No  setup, no patching. Only easy things to be happier. Both their customers and themselves.&lt;br /&gt;&lt;br /&gt;The UI-heavy parts are beign developed with Rails. Some other part is developed with PHP due to performance. Maybe that we will release some rails plugins to give back to the community.&lt;img src="http://feeds.feedburner.com/~r/papipo/~4/5wXtmyXq97M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.codecaster.es/feeds/497604632708441373/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3483689298596906177&amp;postID=497604632708441373" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/497604632708441373?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3483689298596906177/posts/default/497604632708441373?v=2" /><link rel="alternate" type="text/html" href="http://blog.codecaster.es/2006/10/killer-app-hopefully.html" title="Killer App (Hopefully)" /><author><name>Papipo</name><uri>http://www.blogger.com/profile/10673361479709852302</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://bp1.blogger.com/_ndEy9wFW2e8/SIxh0W6yXKI/AAAAAAAAAAU/pQajPQ4FK4w/S220/mypictr_last.fm.jpg" /></author><thr:total>0</thr:total></entry></feed>
