<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Muziboo Development Blog</title>
	
	<link>http://devblog.muziboo.com</link>
	<description>Muziboo development stories. Mostly set in ruby land</description>
	<lastBuildDate>Fri, 01 Apr 2011 04:52:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/muziboodev" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="muziboodev" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Cucumber and i18n with interpolation</title>
		<link>http://devblog.muziboo.com/2011/04/01/cucumber-and-i18n-with-interpolatio/</link>
		<comments>http://devblog.muziboo.com/2011/04/01/cucumber-and-i18n-with-interpolatio/#comments</comments>
		<pubDate>Fri, 01 Apr 2011 04:51:10 +0000</pubDate>
		<dc:creator>prateek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://devblog.muziboo.com/?p=127</guid>
		<description><![CDATA[
			
				
			
		
If you are using cucumber to test a multilingual app, you should check out this post for a step definition that you can use to test multilingual strings. However, most likely you would be using variables in your translation strings. Assuming you have pickle installed (if you don&#8217;t you should), you can use the step [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdevblog.muziboo.com%2F2011%2F04%2F01%2Fcucumber-and-i18n-with-interpolatio%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdevblog.muziboo.com%2F2011%2F04%2F01%2Fcucumber-and-i18n-with-interpolatio%2F&amp;source=muziboo&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>If you are using cucumber to test a multilingual app, you should check out <a href="http://amielmartin.tumblr.com/post/235855133/using-i18n-in-cucumber" onclick="javascript:pageTracker._trackPageview('/outbound/article/amielmartin.tumblr.com');">this post</a> for a step definition that you can use to test multilingual strings. However, most likely you would be using variables in your translation strings. Assuming you have <a href="https://github.com/ianwhite/pickle" onclick="javascript:pageTracker._trackPageview('/outbound/article/github.com');">pickle</a> installed (if you don&#8217;t you should), you can use the step and step definition below to test strings with variable interpolation</p>
<p><script src="https://gist.github.com/897732.js?file=gistfile1.rb"></script></p>
<p>Just like pickle, you can add any number of variables.</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.muziboo.com/2011/04/01/cucumber-and-i18n-with-interpolatio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails + MySQL scaling on a budget</title>
		<link>http://devblog.muziboo.com/2011/03/09/rails-mysql-scaling-on-a-budget/</link>
		<comments>http://devblog.muziboo.com/2011/03/09/rails-mysql-scaling-on-a-budget/#comments</comments>
		<pubDate>Wed, 09 Mar 2011 13:30:36 +0000</pubDate>
		<dc:creator>prateek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://devblog.muziboo.com/?p=112</guid>
		<description><![CDATA[
			
				
			
		
aka .. can&#8217;t throw hardware at it
Just when I decided to focus fulltime on my new startup SupportBee, our first product Muziboo decided to grow (no complaints though). We went from about 10k visits a day to about 30k visits a day in a month&#8217;s time. Muziboo was my first web programming experience and in [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdevblog.muziboo.com%2F2011%2F03%2F09%2Frails-mysql-scaling-on-a-budget%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdevblog.muziboo.com%2F2011%2F03%2F09%2Frails-mysql-scaling-on-a-budget%2F&amp;source=muziboo&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>aka .. can&#8217;t throw hardware at it</p>
<p>Just when I decided to focus fulltime on my new startup <a href="http://supportbee.com" onclick="javascript:pageTracker._trackPageview('/outbound/article/supportbee.com');">SupportBee</a>, our first product <a href="http://www.muziboo.com" >Muziboo</a> decided to grow (no complaints though). We went from about 10k visits a day to about 30k visits a day in a month&#8217;s time. Muziboo was my first web programming experience and in the sprit of a <a href="http://gettingreal.37signals.com/" onclick="javascript:pageTracker._trackPageview('/outbound/article/gettingreal.37signals.com');">real</a> startup, I always postponed worrying about scaling. However, the cracks showed through this time. Here is what we observed</p>
<ul>
<li>Slow page load</li>
<li>High CPU load and disk I/O</li>
<li>MySQL consuming very high CPU consistently</li>
</ul>
<p>Below is a log of what we did to make the site faster</p>
<p><strong>Better Server Monitoring and Logging</strong></p>
<p>You can&#8217;t fix what you can&#8217;t measure. We researched a bit and installed <a href="http://munin-monitoring.org/" onclick="javascript:pageTracker._trackPageview('/outbound/article/munin-monitoring.org');">munin</a>. Apart from the standard plugins (disk, cpu, network) we setup plugins for beanstalk, rails and nginx. This gave us some pretty charts to understand how the system was behaving. Here is an example of what munin charts looks like</p>
<p><img title="Hosted by imgur.com" src="http://i.imgur.com/Ln3aP.png" alt="" /></p>
<p>Not only can you see the current state of the system, you can also see data for past weeks/months/years. If you are not excited by installing munin, you can look at hosted solution like <a href="http://www.serverdensity.com" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.serverdensity.com');">Server Density</a></p>
<p><strong>MySQL slow query log for missing indexes</strong></p>
<p>Rails does not (cannot) add indexes to your database. Rails does not (cannot) add indexes to your database <em>automatically</em>. You will have to figure out what indexes to add based on your queries. This is not a problem for small tables (hundreds or thousands of rows) but its a problem with bigger tables. Fortunately, its easy to find out queries that are not using the index. Apart from listing slow queries, MySQL can list all the queries that don&#8217;t use the index in slow query log. You can enable it by having this directive in your mysql configuration file</p>
<pre>log-queries-not-using-indexes</pre>
<p>We enabled this option and found out that we had a bunch of index less queries. As we added these indexes, mysql&#8217;s cpu usage started going down bringing the system to a much better shape. You can use mysql&#8217;s explain statement to understand your queries better and add indexes. Its a good idea to have explain&#8217;s output in your rails&#8217; log during development. I found this snippet that does it for you</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">unless</span> RAILS_ENV == <span style="color:#996600;">'production'</span>
      <span style="color:#9966CC; font-weight:bold;">module</span> ActiveRecord
        <span style="color:#9966CC; font-weight:bold;">module</span> ConnectionAdapters
          <span style="color:#9966CC; font-weight:bold;">class</span> MysqlAdapter <span style="color:#006600; font-weight:bold;">&amp;</span>lt; AbstractAdapter             <span style="color:#9966CC; font-weight:bold;">def</span> select_with_explain<span style="color:#006600; font-weight:bold;">&#40;</span>sql, name = <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>               explanation = execute_with_disable_logging<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'EXPLAIN '</span> <span style="color:#006600; font-weight:bold;">+</span> sql<span style="color:#006600; font-weight:bold;">&#41;</span>               e = explanation.<span style="color:#9900CC;">all_hashes</span>.<span style="color:#9900CC;">first</span>               exp = e.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>k,v<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#996600;">&quot; | #{k}: #{v} &quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">join</span>               log<span style="color:#006600; font-weight:bold;">&#40;</span>exp, <span style="color:#996600;">'Explain'</span><span style="color:#006600; font-weight:bold;">&#41;</span>               select_without_explain<span style="color:#006600; font-weight:bold;">&#40;</span>sql, name<span style="color:#006600; font-weight:bold;">&#41;</span>             <span style="color:#9966CC; font-weight:bold;">end</span>             <span style="color:#9966CC; font-weight:bold;">def</span> execute_with_disable_logging<span style="color:#006600; font-weight:bold;">&#40;</span>sql, name = <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;">#:nodoc:               #Run a query without logging               @connection.query(sql)             rescue ActiveRecord::StatementInvalid =&amp;gt; exception</span>
              <span style="color:#9966CC; font-weight:bold;">if</span> exception.<span style="color:#9900CC;">message</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;:&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">first</span> =~ <span style="color:#006600; font-weight:bold;">/</span>Packets out of order<span style="color:#006600; font-weight:bold;">/</span>
                <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::StatementInvalid</span>, <span style="color:#996600;">&quot;'Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information.  If you're on Windows, use the Instant Rails installer to get the updated mysql bindings.&quot;</span>
              <span style="color:#9966CC; font-weight:bold;">else</span>
                <span style="color:#CC0066; font-weight:bold;">raise</span>
              <span style="color:#9966CC; font-weight:bold;">end</span>
            <span style="color:#9966CC; font-weight:bold;">end</span>
            alias_method_chain <span style="color:#ff3333; font-weight:bold;">:select</span>, <span style="color:#ff3333; font-weight:bold;">:explain</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Put it in your config/initializers directory as mysql_explain.rb and restart your server. Now you should see output from explain in your logs before your sql queries. One point to note is that throwing memcache is not a substitute for having faster queries.</p>
<p><strong>Beware of MySQL&#8217;s ORDER BY rand()</strong></p>
<p>Even after adding indexes, one of our queries was not using them. On investigating further I found out that MySQL&#8217;s order by rand() is evil. I won&#8217;t go into the specifics now but you can read up more on <a href="http://stackoverflow.com/questions/1244555/how-can-i-optimize-mysqls-order-by-rand-function" onclick="javascript:pageTracker._trackPageview('/outbound/article/stackoverflow.com');">stackoverflow</a>. In short, order by rand() will always do a full table scan. Avoid it.</p>
<p><strong>MySQLDump haz all the locks</strong></p>
<div><a href="http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/dev.mysql.com');">mysqldump</a> is a popular choice for backing up databases. However it locks up all your tables during the backup. What this means is that your rails&#8217; instances cannot access the database during that time and most likely cannot serve any requests. We moved to <a href="http://www.percona.com/docs/wiki/percona-xtrabackup:start" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.percona.com');">Percona&#8217;s xtrabackup </a>to fix this. However this only works for tables that are innodb (in our case, every table).</div>
<p><strong>Moving from mongrel to passenger</strong></p>
<p>Muziboo was started when the world was just moving over from fastcgi to mongrel. Hence we were using a bunch of  mongrels monitored by monit. However, every time you want to add more mongrels, you have to change your monit configuration file to start and monitor more mongrels. Also there is no easy way to reduce the number of mongrels when under less load. Hence we decided to move over to passenger. In passenger, you just have to change the number of max instances in the nginx configuration files and more app instances will be started under load. When the load is lesser, these instances are shut down. All this is automatically done for you.</p>
<p><strong>Taming I/O during rsync</strong></p>
<p>We use rsync to backup uploaded files uploaded by Muziboo&#8217;s user. We have about 1 TB of data and even though the backup is incremental, there is still considerable I/O to check which files have to be moved. To make sure that rsync does not overwhelm everything else, we used the following options</p>
<pre>nice -20 ionice -c2 -n7 /usr/bin/rsync -avz -e ssh --times --size-only --stats ......</pre>
<p>Nice and IONice help you keep the CPU and disk usage low. You can also use it for other cron/background jobs that you run.</p>
<p>With these changes in place, we have been able to accomodate all the growth on a single server (Quadcore + 12 GB RAM). I think with more growth we may have slowers mysql writes and at that point we may need to move to a separate db server.</p>
<p>Read some interesting comments on this post on <a href="http://news.ycombinator.com/item?id=2304747" onclick="javascript:pageTracker._trackPageview('/outbound/article/news.ycombinator.com');">Hacker News</a></p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.muziboo.com/2011/03/09/rails-mysql-scaling-on-a-budget/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Hosting your git repo on your own server</title>
		<link>http://devblog.muziboo.com/2011/02/13/hosting-your-own-git-repo-on-your-server/</link>
		<comments>http://devblog.muziboo.com/2011/02/13/hosting-your-own-git-repo-on-your-server/#comments</comments>
		<pubDate>Sun, 13 Feb 2011 11:05:32 +0000</pubDate>
		<dc:creator>prateek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://devblog.muziboo.com/?p=108</guid>
		<description><![CDATA[
			
				
			
		
Hosting a git repo yourself is a very simple exercise. If you don&#8217;t need (or don&#8217;t want to pay for) features offered by github, you can setup your server to host your git repo. All you need is a server with ssh access. Here are the steps that you need to follow
Login to your server

ssh [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdevblog.muziboo.com%2F2011%2F02%2F13%2Fhosting-your-own-git-repo-on-your-server%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdevblog.muziboo.com%2F2011%2F02%2F13%2Fhosting-your-own-git-repo-on-your-server%2F&amp;source=muziboo&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Hosting a git repo yourself is a very simple exercise. If you don&#8217;t need (or don&#8217;t want to pay for) features offered by github, you can setup your server to host your git repo. All you need is a server with ssh access. Here are the steps that you need to follow</p>
<p>Login to your server</p>
<p><code lang="bash"><br />
ssh tom@example.com<br />
tom@example.com$ mkdir my_repo.git<br />
tom@example.com$ cd my_repo.git<br />
tom@example.com$ git init<br />
</code></p>
<p>On you local machine, where you have your code</p>
<p><code lang="bash"><br />
$ cd my_code # cd to your code<br />
$ git init<br />
$ git add .  # Adds everything. Use .gitignore to ignore some files<br />
$ git remote add origin tom@example.com:my_repo.git<br />
$ git push origin master<br />
</code></p>
<p>Now you can clone tom@example.com:my_repo.git on any number of machines. To not share password, put your public keys on tom@example.com</p>
<p>This approach gives you a basic git setup with ssh access (no http access). These steps should work on shared hosting too (as long as you have git available)</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.muziboo.com/2011/02/13/hosting-your-own-git-repo-on-your-server/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Flexmock Error: undefined method `destroyed?’</title>
		<link>http://devblog.muziboo.com/2010/09/22/flexmock-error-undefined-method-destroyed/</link>
		<comments>http://devblog.muziboo.com/2010/09/22/flexmock-error-undefined-method-destroyed/#comments</comments>
		<pubDate>Wed, 22 Sep 2010 03:54:14 +0000</pubDate>
		<dc:creator>prateek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://devblog.muziboo.com/?p=101</guid>
		<description><![CDATA[
			
				
			
		
If you are using flexmock for testing your rails code and you are mocking an active record model using flexmock(:model, Model), you may get an error like
 undefined method `destroyed?'
The problem is that flexmock defines a lot of methods/attributes like id and new_instance? etc but does not define a destroyed? method that rails now expects. [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdevblog.muziboo.com%2F2010%2F09%2F22%2Fflexmock-error-undefined-method-destroyed%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdevblog.muziboo.com%2F2010%2F09%2F22%2Fflexmock-error-undefined-method-destroyed%2F&amp;source=muziboo&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>If you are using flexmock for testing your rails code and you are mocking an active record model using flexmock(:model, Model), you may get an error like</p>
<p><code style="font-family: Monaco, Consolas, 'DejaVu Sans Mono', monospace; font-size: 11px; color: #444444;"> undefined method `destroyed?'</code></p>
<p>The problem is that flexmock defines a lot of methods/attributes like id and new_instance? etc but does not define a destroyed? method that rails now expects. Fortunately, this is easy to fix. Create a file &#8216;config/initializers/flexmock_extensions.rb&#8217; and put this in</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> FlexMock
  <span style="color:#9966CC; font-weight:bold;">class</span> MockContainerHelper
    <span style="color:#9966CC; font-weight:bold;">def</span> add_model_methods<span style="color:#006600; font-weight:bold;">&#40;</span>mock, model_class, id<span style="color:#006600; font-weight:bold;">&#41;</span>
      container = mock.<span style="color:#9900CC;">flexmock_container</span>
&nbsp;
      mock_errors = container.<span style="color:#9900CC;">flexmock</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;errors&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      mock_errors.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:count</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">by_default</span>
      mock_errors.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:full_messages</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">by_default</span>
&nbsp;
      mock.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span>id<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">by_default</span>
      mock.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:to_params</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span>id.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">by_default</span>
      mock.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:new_record</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">false</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">by_default</span>
      mock.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:class</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span>model_class<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">by_default</span>
      mock.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:errors</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span>mock_errors<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">by_default</span>
      mock.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:destroyed</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">false</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">by_default</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># HACK: Ruby 1.9 needs the following lambda so that model_class</span>
      <span style="color:#008000; font-style:italic;"># is correctly bound below.</span>
      <span style="color:#CC0066; font-weight:bold;">lambda</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
      mock.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:is_a</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span>any<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>other<span style="color:#006600; font-weight:bold;">|</span>
        other == model_class
      <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">by_default</span>
      mock.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:instance_of</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span>any<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>other<span style="color:#006600; font-weight:bold;">|</span>
        other == model_class
      <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">by_default</span>
      mock.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:kind_of</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span>any<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>other<span style="color:#006600; font-weight:bold;">|</span>
        model_class.<span style="color:#9900CC;">ancestors</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>other<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">by_default</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Basically, we are defining the method destroyed? and returning false everytime. Now your tests should work</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.muziboo.com/2010/09/22/flexmock-error-undefined-method-destroyed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pickle (Cucumber) steps for verifying counter cache</title>
		<link>http://devblog.muziboo.com/2010/06/17/pickle-cucumber-steps-for-verifying-counter-cache/</link>
		<comments>http://devblog.muziboo.com/2010/06/17/pickle-cucumber-steps-for-verifying-counter-cache/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 11:39:03 +0000</pubDate>
		<dc:creator>prateek</dc:creator>
				<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://devblog.muziboo.com/?p=94</guid>
		<description><![CDATA[
			
				
			
		
Pickle is a great add on to cucumber as it provides steps for often used scenario. There is a step provided for verifying the association size of an active record instance. Therefore you can write something like
Then the user: &#8220;Joe&#8221; should have 1 friends
and it will check if joe.friends.size == 0. However this does not [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdevblog.muziboo.com%2F2010%2F06%2F17%2Fpickle-cucumber-steps-for-verifying-counter-cache%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdevblog.muziboo.com%2F2010%2F06%2F17%2Fpickle-cucumber-steps-for-verifying-counter-cache%2F&amp;source=muziboo&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><a href="http://github.com/ianwhite/pickle" onclick="javascript:pageTracker._trackPageview('/outbound/article/github.com');">Pickle</a> is a great add on to cucumber as it provides steps for often used scenario. There is a step provided for verifying the association size of an active record instance. Therefore you can write something like</p>
<p>Then the user: &#8220;Joe&#8221; should have 1 friends</p>
<p>and it will check if joe.friends.size == 0. However this does not check the counter cache (if you have one). I modified it a bit to verify counter cache (changes in file features/step_definitions/pickle_steps.rb)</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># assert size of association</span>
<span style="color:#9966CC; font-weight:bold;">Then</span> <span style="color:#006600; font-weight:bold;">/</span>^<span style="color:#008000; font-style:italic;">#{capture_model} should have (\d+) (\w+)$/ do |name, size, association|</span>
  <span style="color:#9966CC; font-weight:bold;">if</span><span style="color:#006600; font-weight:bold;">&#40;</span>model!<span style="color:#006600; font-weight:bold;">&#40;</span>name<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">respond_to</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{association}_count&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    model!<span style="color:#006600; font-weight:bold;">&#40;</span>name<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{association}_count&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should</span> == size.<span style="color:#9900CC;">to_i</span>
  <span style="color:#9966CC; font-weight:bold;">else</span>
    model!<span style="color:#006600; font-weight:bold;">&#40;</span>name<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span>association<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">size</span>.<span style="color:#9900CC;">should</span> == size.<span style="color:#9900CC;">to_i</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This assumes that you counter cache is named association_cache which is the convention in rails&#8217; world.</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.muziboo.com/2010/06/17/pickle-cucumber-steps-for-verifying-counter-cache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple Javascript Queue for Asynchronous Loading</title>
		<link>http://devblog.muziboo.com/2010/04/29/a-simple-javascript-queue-for-asynchronous-loading/</link>
		<comments>http://devblog.muziboo.com/2010/04/29/a-simple-javascript-queue-for-asynchronous-loading/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 08:07:35 +0000</pubDate>
		<dc:creator>prateek</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[javascript optimization page speed]]></category>

		<guid isPermaLink="false">http://devblog.muziboo.com/2010/04/29/a-simple-javascript-queue-for-asynchronous-loading/</guid>
		<description><![CDATA[
			
				
			
		
YSlow is a popular tool for measuring and tweaking site performance. The tool recommends that Javascript be put at the bottom of the page (since javascript blocks the page until its loaded). However one of the challenges of doing this is that you cannot call any javascript function (that you have defined in your js [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdevblog.muziboo.com%2F2010%2F04%2F29%2Fa-simple-javascript-queue-for-asynchronous-loading%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdevblog.muziboo.com%2F2010%2F04%2F29%2Fa-simple-javascript-queue-for-asynchronous-loading%2F&amp;source=muziboo&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><a href="http://developer.yahoo.com/yslow/"target="_blank"  onclick="javascript:pageTracker._trackPageview('/outbound/article/developer.yahoo.com');">YSlow</a> is a popular tool for measuring and tweaking site performance. The tool <a href="http://developer.yahoo.com/performance/rules.html#js_bottom"target="_blank"  onclick="javascript:pageTracker._trackPageview('/outbound/article/developer.yahoo.com');">recommends</a> that Javascript be put at the bottom of the page (since javascript blocks the page until its loaded). However one of the challenges of doing this is that you cannot call any javascript function (that you have defined in your js files) before the files are loaded. This can be a serious limitation if you are doing a dynamic website where the header and footer (which is where the script tags are inserted) is static and all the dynamic content is in the middle of the page. If you have used any Ruby on Rails or similar framework, you know what I mean. Basically, its hard to put different code in the footer for different pages. </p>
<p>Lets take an example from <a href="http://www.muziboo.com"target="_blank"  >Muziboo</a>. I have a function in javascript to initialize the flash player <i>Muziboo.Player.embedSingle()</i>. If my script tags (for including the js) are in the header, I can make this call anywhere on the page and it will work. However if the javascript files are loaded last, this call has to be made after loading the javascript. </p>
<p><script src="http://gist.github.com/383286.js"></script></p>
<p>However you can overcome this limitation by using a javascript queue that holds the function calls till the external javascript files are loaded. Once the javascript is loaded, it can look at the queue and process the messages. So something like this would work</p>
<p><script src="http://gist.github.com/383288.js"></script></p>
<p>This idea is not new and is used by <a href="http://code.google.com/apis/analytics/docs/tracking/asyncTracking.html" target="_blank" onclick="javascript:pageTracker._trackPageview('/outbound/article/code.google.com');">Google Analytics&#8217; async tracking</a> code. Lets see how to implement such a queue in javascript (using the prototype.js javascript library)</p>
<p><script src="http://gist.github.com/383291.js"></script></p>
<p>The queue is nothing but a simple javascript array. The process message simply pops out each message, executes it and then changes the push method on _muzq object to execute the message instead of storing it (since now the js is loaded and there is no need to wait). I am still trying to find out a better way than to use eval but this implementation works.</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.muziboo.com/2010/04/29/a-simple-javascript-queue-for-asynchronous-loading/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Updated Blackbook gem</title>
		<link>http://devblog.muziboo.com/2010/04/06/updated-blackbook-gem/</link>
		<comments>http://devblog.muziboo.com/2010/04/06/updated-blackbook-gem/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 15:28:45 +0000</pubDate>
		<dc:creator>prateek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[blackbook]]></category>
		<category><![CDATA[gem]]></category>

		<guid isPermaLink="false">http://devblog.muziboo.com/?p=90</guid>
		<description><![CDATA[
			
				
			
		
I just pushed some changes to my fork of the blackbook address book importer gem. Here is a list of changes

The gem now works with the latest version of mechanize and nokogiri
Myspace and Gmail importer working perfectly. Myspace had changed its url scheme and also address book rendering stuff so the gem was broken for [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdevblog.muziboo.com%2F2010%2F04%2F06%2Fupdated-blackbook-gem%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdevblog.muziboo.com%2F2010%2F04%2F06%2Fupdated-blackbook-gem%2F&amp;source=muziboo&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>I just pushed some changes to my fork of the <a href="http://github.com/prateekdayal/blackbook" onclick="javascript:pageTracker._trackPageview('/outbound/article/github.com');">blackbook address book importer gem</a>. Here is a list of changes</p>
<ul>
<li>The gem now works with the latest version of mechanize and nokogiri</li>
<li>Myspace and Gmail importer working perfectly. Myspace had changed its url scheme and also address book rendering stuff so the gem was broken for a while</li>
</ul>
<p>Sadly the yahoo address book importer is not working as yahoo as added a captcha before csv download. I will try to use an alternative view and fix the issue sometime soon.  I have not tried aol and hotmail import.</p>
<p>If you need any help, please leave a comment here.</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.muziboo.com/2010/04/06/updated-blackbook-gem/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Externalinterface not working in Firefox but working in IE for invisible swf</title>
		<link>http://devblog.muziboo.com/2009/11/26/externalinterface-not-working-in-firefox-but-working-in-ie-for-invisible-swf/</link>
		<comments>http://devblog.muziboo.com/2009/11/26/externalinterface-not-working-in-firefox-but-working-in-ie-for-invisible-swf/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 05:20:35 +0000</pubDate>
		<dc:creator>prateek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[error]]></category>

		<guid isPermaLink="false">http://devblog.muziboo.com/?p=87</guid>
		<description><![CDATA[
			
				
			
		
Yes &#8230; as unrealistic as it may sound, yesterday, I ran into an issue where something worked in Internet explorer but not in Firefox. I was trying to call an actionscript functions on a swf file from javascript. This is a fairly standard thing and is well documented on the web. I followed all the [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdevblog.muziboo.com%2F2009%2F11%2F26%2Fexternalinterface-not-working-in-firefox-but-working-in-ie-for-invisible-swf%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdevblog.muziboo.com%2F2009%2F11%2F26%2Fexternalinterface-not-working-in-firefox-but-working-in-ie-for-invisible-swf%2F&amp;source=muziboo&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Yes &#8230; as unrealistic as it may sound, yesterday, I ran into an issue where something worked in Internet explorer but not in Firefox. I was trying to call an actionscript functions on a swf file from javascript. This is a fairly standard thing and is <a href="http://www.adobe.com/devnet/flash/articles/external_interface_06.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.adobe.com');">well documented</a> on the web. I followed all the steps (registering a callback and embedding the swf using <a href="http://code.google.com/p/swfobject/" onclick="javascript:pageTracker._trackPageview('/outbound/article/code.google.com');">swfobject</a> library) and it worked perfectly in IE. I could call my actionscript functions using javascript in IE but in firefox it would occasionally fail and I would see the following two messages in firebug</p>
<p><em><strong>uncaught exception: [Exception... "Failure" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: http://localhost:9001/javascripts/swfobject.js?1259133537 :: anonymous :: line 4" data: no]</strong></em></p>
<p><em><strong>$(&#8217;movieName&#8217;).asFunc() undefined method </strong></em></p>
<p>where <em>movieName</em> is the id of the swf file and <em>asFunc</em> is the function defined in actionscript using ExternalInterface.addCallback. After a lot of googling, I ran into <a href="http://www.kirupa.com/forum/showpost.php?p=2310986&amp;postcount=2" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.kirupa.com');">this thread</a> which explained the basic problem. Since my swf file was hidden in the footer of the page, the callbacks worked after I had once scrolled down and seen the footer. Yes as crazy as it sounds, that was really the problem.  Firefox wants you to see the swf once before you make the function call.  To make sure that the 1&#215;1 sized swf file was always visible no matter where you are in the page, I added the following css rule</p>
<p>#movieName {<br />
position: fixed;<br />
top: 0;<br />
left: 0;<br />
}</p>
<p>This rule makes sure that no matter how much you scroll up or scroll down, the swf file is always at the same place (in this case, just at the starting of the page, relative to the browser window). You can read more about fixed positioning <a href="http://www.w3schools.com/Css/css_positioning.asp" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.w3schools.com');">here</a>. I am sure there must be a better explanation/solution for this problem but I have tried my approach and it atleast works. If you find a better solution, please post as a comment and I will update the post.</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.muziboo.com/2009/11/26/externalinterface-not-working-in-firefox-but-working-in-ie-for-invisible-swf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Resizing existing images uploaded using file_column</title>
		<link>http://devblog.muziboo.com/2009/11/14/resizing-existing-images-uploaded-using-file_column/</link>
		<comments>http://devblog.muziboo.com/2009/11/14/resizing-existing-images-uploaded-using-file_column/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 06:48:56 +0000</pubDate>
		<dc:creator>prateek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://devblog.muziboo.com/?p=83</guid>
		<description><![CDATA[
			
				
			
		
File column is a great plugin by Sebastian Kanthak for uploading images (and other files) in a rails&#8217; site. The plugin has rmagick integration and can create thumbnails automatically for you. We use it for Muziboo and have been pretty happy with it (yes despite the rmagick dependency). We recently had to update the thumbnail [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdevblog.muziboo.com%2F2009%2F11%2F14%2Fresizing-existing-images-uploaded-using-file_column%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdevblog.muziboo.com%2F2009%2F11%2F14%2Fresizing-existing-images-uploaded-using-file_column%2F&amp;source=muziboo&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><a href="http://www.kanthak.net/opensource/file_column/" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.kanthak.net');">File column</a> is a great plugin by Sebastian Kanthak for uploading images (and other files) in a rails&#8217; site. The plugin has rmagick integration and can create thumbnails automatically for you. We use it for <a href="http://www.muziboo.com" >Muziboo</a> and have been pretty happy with it (yes despite the rmagick dependency). We recently had to update the thumbnail dimensions for a few of our models. Its fairly simple to change the thumbnail sizes in the model and all new uploads are resized to new dimensions. However, the existing images are not automatically changed for you . Thankfully, on digging deeper into the code I found that there is pretty simple way to accomplish that. Lets say you have a user model (with a file_column field photo) and you want to update the thumbnails for all existing images. You just need to simply run the following commands</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">User.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>,:conditions <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;photo IS NOT NULL&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>u<span style="color:#006600; font-weight:bold;">|</span>
  u.<span style="color:#9900CC;">photo</span> = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>u.<span style="color:#9900CC;">photo</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  u.<span style="color:#9900CC;">save</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Ofcourse if you have a lot of users, you may wanna fetch them in batches. Also image resizing is a pretty CPU intensive operation so you may wanna watch out for that. Once the operation is over, you will have updated thumbnails for all your previously uploaded images.</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.muziboo.com/2009/11/14/resizing-existing-images-uploaded-using-file_column/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Authentication error while fetching gmail contacts using blackbook</title>
		<link>http://devblog.muziboo.com/2009/09/17/authentication-error-while-fetching-gmail-contacts-using-blackbook/</link>
		<comments>http://devblog.muziboo.com/2009/09/17/authentication-error-while-fetching-gmail-contacts-using-blackbook/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 08:56:34 +0000</pubDate>
		<dc:creator>prateek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://devblog.muziboo.com/?p=67</guid>
		<description><![CDATA[
			
				
			
		
Blackbook gem can be used to fetch contacts from gmail, yahoo and hotmail address books. However I recently found out that it would throw up a &#8216;Must be authenticated to access contacts&#8217; error everytime I tried to import gmail contacts. On digging deeper, I found out that google has changed the contents of its cookie and blackbook uses this cookie [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdevblog.muziboo.com%2F2009%2F09%2F17%2Fauthentication-error-while-fetching-gmail-contacts-using-blackbook%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdevblog.muziboo.com%2F2009%2F09%2F17%2Fauthentication-error-while-fetching-gmail-contacts-using-blackbook%2F&amp;source=muziboo&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><a href="http://github.com/purzelrakete/blackbook" onclick="javascript:pageTracker._trackPageview('/outbound/article/github.com');">Blackbook</a> gem can be used to fetch contacts from gmail, yahoo and hotmail address books. However I recently found out that it would throw up a &#8216;Must be authenticated to access contacts&#8217; error everytime I tried to import gmail contacts. On digging deeper, I found out that google has changed the contents of its cookie and blackbook uses this cookie to make sure that the user is authenticated. To fix the issue, you just need to make a one line change in the function <em>scrape_contacts</em> in the file <em>lib/blackbook/importer/gmail.rb. </em></p>
<p>Change</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">unless</span> agent.<span style="color:#9900CC;">cookies</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>c<span style="color:#006600; font-weight:bold;">|</span> c.<span style="color:#9900CC;">name</span> == <span style="color:#996600;">'GAUSR'</span>  <span style="color:#006600; font-weight:bold;">&amp;</span>amp;<span style="color:#006600; font-weight:bold;">&amp;</span>amp;
  c.<span style="color:#9900CC;">value</span> == <span style="color:#996600;">&quot;mail:#{options[:username]}&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#CC0066; font-weight:bold;">raise</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#6666ff; font-weight:bold;">Blackbook::BadCredentialsError</span>, <span style="color:#996600;">&quot;Must be authenticated to access contacts.&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>to</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">unless</span> agent.<span style="color:#9900CC;">cookies</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>c<span style="color:#006600; font-weight:bold;">|</span> c.<span style="color:#9900CC;">name</span> == <span style="color:#996600;">'GAUSR'</span> <span style="color:#006600; font-weight:bold;">&amp;</span>amp;<span style="color:#006600; font-weight:bold;">&amp;</span>amp;
  <span style="color:#006600; font-weight:bold;">&#40;</span>c.<span style="color:#9900CC;">value</span> =~ <span style="color:#006600; font-weight:bold;">/</span>mail.<span style="color:#006600; font-weight:bold;">*</span>:<span style="color:#008000; font-style:italic;">#{options[:username]}/)!=nil}</span>
<span style="color:#CC0066; font-weight:bold;">raise</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#6666ff; font-weight:bold;">Blackbook::BadCredentialsError</span>, <span style="color:#996600;">&quot;Must be authenticated to access contacts.&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>If you want to install the updated gem instead of making the change, you can find it in <a href="http://github.com/prateekdayal/blackbook" onclick="javascript:pageTracker._trackPageview('/outbound/article/github.com');">my blackbook fork</a>. My fork also includes the <a href="http://devblog.muziboo.com/2009/07/02/myspace-email-address-book-import-in-ruby/" >myspace address book import</a></p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.muziboo.com/2009/09/17/authentication-error-while-fetching-gmail-contacts-using-blackbook/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

