<?xml version="1.0" encoding="UTF-8"?>
<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/"
	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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Pedro Mateus Tavares</title>
	<atom:link href="http://pedromtavares.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://pedromtavares.wordpress.com</link>
	<description>Software Developer</description>
	<lastBuildDate>Sun, 25 Dec 2011 16:28:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='pedromtavares.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Pedro Mateus Tavares</title>
		<link>http://pedromtavares.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://pedromtavares.wordpress.com/osd.xml" title="Pedro Mateus Tavares" />
	<atom:link rel='hub' href='http://pedromtavares.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Using NodeJS to Stream a Radio Broadcast</title>
		<link>http://pedromtavares.wordpress.com/2011/08/15/using-nodejs-to-stream-a-radio-broadcast/</link>
		<comments>http://pedromtavares.wordpress.com/2011/08/15/using-nodejs-to-stream-a-radio-broadcast/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 00:31:54 +0000</pubDate>
		<dc:creator>pedromtavares</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://pedromtavares.wordpress.com/?p=538</guid>
		<description><![CDATA[So recently I was invited to compete on NodeKnockout (similar to RailsRumble) by one of Brazil&#8217;s best JS developers, the &#8230;<p><a href="http://pedromtavares.wordpress.com/2011/08/15/using-nodejs-to-stream-a-radio-broadcast/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=538&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>So recently I was invited to compete on <a href="http://nodeknockout.com">NodeKnockout</a> (similar to RailsRumble) by <a href="http://about.me/cmilfont">one of Brazil&#8217;s best JS developers</a>, the thing was, I had never done NodeJS in my life, and the competition is like in a few weeks time, so for the sake of not slowing the team down I decided to write an app to get familiar with it.</p>
<h1>Background</h1>
<p>I started out with the <a href="http://peepcode.com/products/nodejs-i">NodeJS Peepcode screencast</a>, which lays down <a href="http://github.com/pedromtavares/livestats">a pretty cool app</a> which I <a href="http://stats.universit.as">immediately hooked</a> to my <a href="http://universit.as">Rails side project</a>. A week later I started looking in ways to broadcast a stream of music from <a href="http://www.virtualdj.com">VirtualDJ</a>, since I&#8217;m a kind of an <a href="http://soundcloud.com/pedromtavares/alpha-mix">amateur DJ myself</a> and wanted a way to play stuff to my friends through the internet. Through some research I came across <a href="http://www.shoutcast.com/">Shoutcast</a>, which, as Wikipedia states, is a &#8220;cross-platform proprietary software for streaming media over the Internet&#8221;. The cool thing is that they have server packages which you can just download and install on your computer, so since I have a Linode VPS box I got it quickly set up on <a href="http://stream.pedromtavares.com">http://stream.pedromtavares.com</a>.</p>
<p>But having a radio stream is not enough, nor does it have anything to do with programming since it&#8217;s just server configuration, so where does Node come in? A Shoutcast stream sends buffered audio data, which is perfectly readable by audio players such as iTunes, Windows Media Player and Winamp because they have internal decoders, but something like an HTML5 audio tag can&#8217;t read that buffer directly, and that&#8217;s where an HTTP decoding proxy comes in. A quick search on StackOverFlow miraculously got me started with <a href="http://stackoverflow.com/questions/3955103/streaming-audio-from-a-node-js-server-to-html5-audio-tag">very simple solution</a> that worked on Chrome out of the box. From that example I found <a href="https://github.com/TooTallNate/">the creator</a> of the radio-stream package, which was also the owner of <a href="https://github.com/TooTallNate/node-icecast-stack">icecast-stack</a> (a rewrite of radio-stream). The icecast-stack repo has some examples in it, being the most relevant to our case the <a href="https://github.com/TooTallNate/node-icecast-stack/blob/master/examples/simpleProxy/proxy.js">simpleProxy</a>, which was the solid foundation for all my work.</p>
<h1>Walkthrough the code</h1>
<p>Enough talking, let&#8217;s go over the things I did on top of that simpleProxy example and how everything is working together. First things first, the code repository for my radio is <a href="https://github.com/pedromtavares/radio">hosted on GitHub</a>, so make sure you open it to follow along. Just to clear out the architecture, we have a Shoutcast server (which I&#8217;ll call radio server) which sends the stream to our Node HTTP server (which I&#8217;ll call proxy), we have our income source (VirtualDJ for my case) which feeds data into the radio server, and the browser, which plays data coming from the proxy.</p>
<p>The most important feature is to, obviously, decode and stream audio, and the code for that is all in the <a href="https://github.com/pedromtavares/radio/blob/master/lib/decoder.js">decoder.js</a> file. We basically start an instance of Decoder, and with it also start a stream of raw PCM data, which we&#8217;ll basically use to write all data that comes from the stream and later decode to mp3/ogg depending on what is asked from the web server. This stream of raw data on STDIN is also useful for a very cool feature called &#8220;Burst-On-Connect&#8221;, which is basically a buffer of about 2MB of data that will get played immediately when requested, so we don&#8217;t have to make the user wait for the radio server to send data to the proxy for the browser to actually play something &#8212; we can just send the buffered data immediately.</p>
<p>So we already have data ready to be streamed in our STDIN that&#8217;s getting endlessly fed from the radio server, what now? Now we can have our audio tag (or flash player) point to a url such as /stream.mp3, and route that to our mp3 decoder, which will start an mp3 stream that can be read by the audio tag/flash player, and the same goes for /stream.ogg, which is also necessary because some browsers can&#8217;t stream mp3 data.</p>
<p>Ok, so moving away from the decoder and into the web server, we have quite a few things to look at. The second most important feature after streaming the audio is showing the current track being played, and that&#8217;s dealt with a really cool browser feature called <a href="http://en.wikipedia.org/wiki/WebSocket">WebSockets</a>, which is basically a thin connection that the server keeps with each of its clients, sending them messages whenever needed. With that in our hands, it becomes really easy to implement real-time track updates, we just need to treat an event (called a &#8216;metadata&#8217; event) on the proxy that receives information from the radio server that a new track is playing, and spread that out to all clients connected through WebSockets, which is all done through the <a href="http://faye.jcoglan.com/">Faye</a> package.</p>
<p>Another pretty cool thing that was implemented is the stream reconnection feature, where the proxy will go into standby mode when the input source disconnects from the radio server (thus closing the stream), until another source connects and a new stream is stablished. Node makes this extremely easy to handle since everything in it is event-driven.</p>
<p>But users don&#8217;t care about all this crap, so we need to deal with the front-end also. Unfortunately HTML5 audio players will only go so far, so I decided to use an awesome jQuery player called <a href="http://www.jplayer.org/">jPlayer</a>, which uses the Audio API (instead of relying on native HTML5 audio players) on a very nice looking player. It also has a fallback to a Flash Player for old browsers, and all of this is handled through a common API, so all the JS you write for the player will work no matter what.</p>
<h1>The result</h1>
<p>You can check out what became of all this at <a href="http://radio.pedromtavares.com">http://radio.pedromtavares.com</a>, the site is in portuguese but it doesn&#8217;t really matter since none of what&#8217;s written is of major importance, and chances are the radio will be offline when you access it, but you can leave the tab open all day long and when a stream starts the page will automagically start playing it (hurray for WebSockets!). &#8220;BUT DOES IT SCALE?&#8221;, you ask. Well, I haven&#8217;t managed to get a lot of people connected at it at once since I finished writing it like 2 days ago, but I did manage to get 10~15 people simultaneously and nobody complained about it, so I guess we&#8217;re off to a good start.</p>
<p>I plan on adding more features to the radio such as a chat (for song requests) and a track history (using a database), so stay stuned more things to come. And, of course, since the project is open source, feel free to contribute, I know very little about audio encoding and already stated that I am a Node noob, so the code is far from perfect and could use an expert hand. And also, if you have VirtualDJ 7 Pro installed, I&#8217;ll gladly stream your tracks, just hit me at <a href="mailto:pedro@pedromtavares.com">pedro@pedromtavares.com</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pedromtavares.wordpress.com/538/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pedromtavares.wordpress.com/538/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pedromtavares.wordpress.com/538/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pedromtavares.wordpress.com/538/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pedromtavares.wordpress.com/538/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pedromtavares.wordpress.com/538/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pedromtavares.wordpress.com/538/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pedromtavares.wordpress.com/538/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pedromtavares.wordpress.com/538/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pedromtavares.wordpress.com/538/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pedromtavares.wordpress.com/538/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pedromtavares.wordpress.com/538/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pedromtavares.wordpress.com/538/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pedromtavares.wordpress.com/538/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=538&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pedromtavares.wordpress.com/2011/08/15/using-nodejs-to-stream-a-radio-broadcast/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9ee2698da5765a84991264f0a612d661?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">pedromtavares</media:title>
		</media:content>
	</item>
		<item>
		<title>Call to Arms: Universitas!</title>
		<link>http://pedromtavares.wordpress.com/2011/06/23/call-to-arms-universitas/</link>
		<comments>http://pedromtavares.wordpress.com/2011/06/23/call-to-arms-universitas/#comments</comments>
		<pubDate>Thu, 23 Jun 2011 14:55:22 +0000</pubDate>
		<dc:creator>pedromtavares</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://pedromtavares.wordpress.com/?p=518</guid>
		<description><![CDATA[As I&#8217;ve mentioned on previous blog posts, I&#8217;ve been spending a lot of time working on my side project lately, &#8230;<p><a href="http://pedromtavares.wordpress.com/2011/06/23/call-to-arms-universitas/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=518&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;ve mentioned on previous blog posts, I&#8217;ve been spending a lot of time working on my side project lately, which I&#8217;m glad to announce has reached its first releasable version, which you can check out at <a href="http://universit.as" target="_blank">universit.as</a>.</p>
<p>The thing is, it&#8217;s &#8216;releasable&#8217;, but it&#8217;s too basic, it has its major features which I consider to be appealing, but it lacks those small details which makes a platform addicting and that makes it clear to everyone what it&#8217;s all about. So after reaching this first usable version, I decided it was time to ask for help. I alone won&#8217;t be able to take this platform to the maturity it deserves, and since its code is all open source anyways, why not make a huge call to arms to all Rails developers and designers out there?</p>
<p>I did my best to &#8216;sell&#8217; the application to users by describing it as much as possible on its homepage, now I&#8217;m gonna convince you on why you, as a Rails developer or designer with some time spare time, should help me out building this thing and make it also YOUR side project.</p>
<h2>The Tech</h2>
<p>All of us geeks love hearing about tech, so let&#8217;s get that out of the way first. Universitas is a Ruby on Rails 3 application running on top of NGINX, Unicorn, Ruby 1.9.2 (on RVM) and MySQL, all on a Linode Ubuntu 10.04 box with its code being <a href="https://github.com/pedromtavares/universitas" target="_blank">hosted on GitHub</a>. Some on the gems include Devise, OmniAuth, InheritedResources and CarrierWave. RSpec is being used for unit testing, Steak for acceptance testing (started using it before the Capybara update) and Factory Girl for mocking. Amazon S3 is also being used for storage since one of the project&#8217;s main feature is document uploading. Oh, and let&#8217;s not forget about HAML for presentation (haters gonna hate).</p>
<h2>Use it as your playground</h2>
<p>I use Universitas to test out new stuff. Take a look at the <a href="https://github.com/pedromtavares/universitas/blob/master/Gemfile" target="_blank">application Gemfile</a> and see what gems are being used, I try my best to test out every new thing (that&#8217;s in the context of the application, of course) that comes out on news channels such as Railscasts, Ruby5, RubyInside and so on. You probably don&#8217;t get to use all of these new things on your job, so here&#8217;s your chance to have a live production app where you can just go wild and see if that gem you heard about is really as cool as they say.</p>
<h2>Use it as a practice ground</h2>
<p>Sometimes you need to deliver fast because you have deadlines. We&#8217;ve all been there. And sometimes, when in a hurry, we write some code which we&#8217;re not really proud of, but that gets the job done nevertheless. We also don&#8217;t experiment new coding techniques or not break existing legacy patterns, because you shouldn&#8217;t be practicing at the cost of being wrong, you should do what you know will work.</p>
<p>Well, since we have no deadlines in Universitas, you don&#8217;t have to be in a hurry, so you can just write code, refactor it to look the best it can, and ultimately try out new things that will raise your skill level as a programmer, which is the whole point behind a side project.</p>
<h2>Go wild with your ideas</h2>
<p>As I said, I am only one person, and I can&#8217;t think of everything, so if you have tons of cool ideas about the project, I don&#8217;t see why we shouldn&#8217;t put them on the table and start working on them. The project is extremely green and in need of more minds to polish it.</p>
<p>I&#8217;ve created <a href="https://www.pivotaltracker.com/projects/98111" target="_blank">a public project on Pivotal Tracker</a> for Universitas so you guys can check out some features I thought of after this first release. Anyone in the project will, obviously, be able to add stories and start working on any story they want.</p>
<h2>Be a part of something useful</h2>
<p>Universitas isn&#8217;t just for kicks, it has a solid idea which I believe is of great use to lots of people, since we all know too well that Google Groups does a poor job doing what it does and that someone could do much better. Let that someone be us. I think a level of seriousness and vision is needed for everything, and if I wasn&#8217;t serious about this, I wouldn&#8217;t be willing to alone pay all the bills necessary (such as S3 storage, server and domain (which was NOT cheap)). Last but not least, the &#8216;big picture&#8217; behind Universitas is to become a huge information reference, where you would go when you want to learn something and build a solid community around something you know about.</p>
<hr />
<p>If you got interested (if you read all the way down to here then you probably did), drop me a line at <a href="mailto:pedromateustavares@gmail.com">pedromateustavares@gmail.com</a> so we can get you set up. I&#8217;m not too picky, but I need people with at least some experience in Rails that have built 2 or 3 Rails apps and knows how the flow goes. The project is simple enough to pick up in a couple of hours, so the time between setting it up in your environment and starting to work on a feature will be minimal, and I am online almost all the time to answer any questions and help out anyway I can.</p>
<p>So, what are you waiting for? To arms!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pedromtavares.wordpress.com/518/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pedromtavares.wordpress.com/518/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pedromtavares.wordpress.com/518/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pedromtavares.wordpress.com/518/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pedromtavares.wordpress.com/518/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pedromtavares.wordpress.com/518/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pedromtavares.wordpress.com/518/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pedromtavares.wordpress.com/518/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pedromtavares.wordpress.com/518/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pedromtavares.wordpress.com/518/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pedromtavares.wordpress.com/518/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pedromtavares.wordpress.com/518/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pedromtavares.wordpress.com/518/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pedromtavares.wordpress.com/518/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=518&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pedromtavares.wordpress.com/2011/06/23/call-to-arms-universitas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9ee2698da5765a84991264f0a612d661?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">pedromtavares</media:title>
		</media:content>
	</item>
		<item>
		<title>Getting Your Rails 3 App&#8217;s Routes at Runtime</title>
		<link>http://pedromtavares.wordpress.com/2011/05/23/getting-your-rails-3-apps-routes-at-runtime/</link>
		<comments>http://pedromtavares.wordpress.com/2011/05/23/getting-your-rails-3-apps-routes-at-runtime/#comments</comments>
		<pubDate>Mon, 23 May 2011 03:39:34 +0000</pubDate>
		<dc:creator>pedromtavares</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://pedromtavares.wordpress.com/?p=508</guid>
		<description><![CDATA[Recently on my side project I came across an interesting problem: how could I get all the route paths in &#8230;<p><a href="http://pedromtavares.wordpress.com/2011/05/23/getting-your-rails-3-apps-routes-at-runtime/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=508&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Recently on <a href="http://universit.as">my side project</a> I came across an interesting problem: how could I get all the route paths in my Rails 3 app at runtime? I needed a way to get this information because the app uses a record&#8217;s attribute to directly set the path to it through a friendly URL, such as <a href="http://universit.as/ruby">http://universit.as/ruby</a>, so if a user created a record called &#8216;dashboard&#8217;, that would conflict with the &#8216;dashboard&#8217; path and always show the dashboard page instead of the intended record page. As you can see, this is a terrible security flaw if we consider more serious scenarios.</p>
<p>Back to the initial problem, I figured I could work with a result similar to what the well-known &#8220;rake routes&#8221; prints out, so there I went to the Rails source code to see how it worked: <a href="https://github.com/rails/rails/blob/master/railties/lib/rails/tasks/routes.rake">https://github.com/rails/rails/blob/master/railties/lib/rails/tasks/routes.rake</a></p>
<p>After looking at it for 5 seconds or so, we can immediately notice how easy it is to get the app&#8217;s routes:<br />
<pre class="brush: ruby;">
all_routes = Rails.application.routes.routes
</pre></p>
<p>Although it seems like that loading the whole app&#8217;s route mapping would be slow, it actually isn&#8217;t because they&#8217;re only loaded once when the Rails environment is loaded (when the server starts), so you basically get this for free.</p>
<p>So after mapping that array to the route&#8217;s path (you can get other attributes too, check the Rails source link) and doing some string manipulation, I managed to get a pretty satisfying result:<br />
<pre class="brush: ruby;">
Rails.application.routes.routes.map{|r| r.path.split('/').second}.compact.uniq
# currently returns [&quot;profile&quot;, &quot;users&quot;, &quot;users(.:format)&quot;, &quot;groups&quot;, &quot;groups(.:format)&quot;, &quot;documents&quot;, &quot;documents(.:format)&quot;, &quot;updates(.:format)&quot;, &quot;updates&quot;, &quot;authentications(.:format)&quot;, &quot;authentications&quot;, &quot;home(.:format)&quot;, &quot;about(.:format)&quot;, &quot;track.js(.:format)&quot;, &quot;textile_guide(.:format)&quot;, &quot;:id(.:format)&quot;, &quot;auth&quot;, &quot;rails&quot;] 
</pre></p>
<p>It&#8217;s not perfect but it&#8217;s definitely something I can work with on a validation like so:<br />
<pre class="brush: ruby;">
validates :name, :uniqueness =&gt; true, :presence =&gt; true, :exclusion =&gt; {:in =&gt; Rails.application.routes.routes.map{|r| r.path.split('/').second}.compact.uniq}
</pre></p>
<p>Hope this small tip saves the next dev some time (looking at Rails source wasn&#8217;t my first action either, although it should be).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pedromtavares.wordpress.com/508/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pedromtavares.wordpress.com/508/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pedromtavares.wordpress.com/508/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pedromtavares.wordpress.com/508/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pedromtavares.wordpress.com/508/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pedromtavares.wordpress.com/508/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pedromtavares.wordpress.com/508/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pedromtavares.wordpress.com/508/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pedromtavares.wordpress.com/508/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pedromtavares.wordpress.com/508/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pedromtavares.wordpress.com/508/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pedromtavares.wordpress.com/508/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pedromtavares.wordpress.com/508/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pedromtavares.wordpress.com/508/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=508&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pedromtavares.wordpress.com/2011/05/23/getting-your-rails-3-apps-routes-at-runtime/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9ee2698da5765a84991264f0a612d661?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">pedromtavares</media:title>
		</media:content>
	</item>
		<item>
		<title>Endless Page Scrolling with Rails 3 and jQuery</title>
		<link>http://pedromtavares.wordpress.com/2011/05/08/endless-page-scrolling-with-rails-3-and-jquery/</link>
		<comments>http://pedromtavares.wordpress.com/2011/05/08/endless-page-scrolling-with-rails-3-and-jquery/#comments</comments>
		<pubDate>Mon, 09 May 2011 02:41:43 +0000</pubDate>
		<dc:creator>pedromtavares</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://pedromtavares.wordpress.com/?p=492</guid>
		<description><![CDATA[We are all used to common content pagination, where you have tons of links pointing to other pages with more &#8230;<p><a href="http://pedromtavares.wordpress.com/2011/05/08/endless-page-scrolling-with-rails-3-and-jquery/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=492&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>We are all used to common content pagination, where you have tons of links pointing to other pages with more results. The main reason behind this is performance, after all, you&#8217;re not mad to render tons of records at once and slow down your application on each gigantic request. But then we come to a discussion about usability and how wouldn&#8217;t it be a better user experience to load more records asynchronously as the user scrolls down instead of requiring him to click a link and re-render the entire page, specially when it comes to things such as feeds, where people are already scrolling down a ton of content and wouldn&#8217;t like to hit any sort of &#8216;STOP&#8217; sign on their scrolling.</p>
<p>After spending some time dealing with this <a href="http://universit.as">on my side project</a>, I came up with a nice and simple endless page scrolling solution with jQuery and Rails 3. I created <a href="http://endless-scroll-example.heroku.com/">an example application</a> for a more practical view on our problem and hosted all its code <a href="https://github.com/pedromtavares/endless_scroll_example">at this Github repository</a> for anyone to check out.</p>
<p>First off, the whole endless scrolling Javascript front-end is a courtesy of <a href="https://github.com/fredwu/jquery-endless-scroll">this plugin</a>, although it lacks a huge improvement which I&#8217;ll talk about later, so case you want to use it, I recommend downloading <a href="https://github.com/pedromtavares/endless_scroll_example/blob/master/public/javascripts/jquery.endless-scroll.js">my version</a> instead.</p>
<p>On the back-end side of things, I decided it was better to to ditch pagination plugins such as will_paginate altogether and load records not based on an &#8216;offset&#8217; parameter, but on a &#8216;last timestamp&#8217; parameter, this way if the feed happens to update while you&#8217;re scrolling down you won&#8217;t get duplicated results on the bottom due to the database offset pushing older (and already rendered) records to the bottom, thus loading them again. Also, it&#8217;s important to somehow stop the endless scrolling when there are no more results to show, so the user doesn&#8217;t spam our server with useless requests. So we basically need to manage 3 things: appending new records to our already existent list through AJAX, update the &#8216;last timestamp&#8217; parameter somewhere with each re-render and know when to stop asking for more.</p>
<p>Let&#8217;s get down to the code, starting with the JS:<br />
<pre class="brush: jscript;">
$('ul').endlessScroll({
  fireOnce: true,
  fireDelay: 500,
	ceaseFire: function(){
	  return $('#infinite-scroll').length ? false : true;
	},
	callback: function(){
	  $.ajax({
		  url: '/posts',
		  data: {
			  last: $(this).attr('last')
		  },
		  dataType: 'script'
		});
	}
});
</pre></p>
<p>Assuming we have an UL with a fixed height, an overflow:auto and a &#8216;last&#8217; attribute, this code will make requests to the specified URL on each scroll event (you can configure the scrolling distance with the bottomPixels property) and stop making them when we don&#8217;t have an #infinite-scroll div. The original plugin would not check for this ceaseFire condition on EACH scrolling event, which is crucial here (or else, what&#8217;s the point in having it?), that&#8217;s why using my patched version is key. This is how our page should look like to be ready to receive the upcoming updates:</p>
<p><pre class="brush: ruby;">
&lt;% unless @posts.blank?%&gt;
  &lt;ul class='list' last=&quot;&lt;%=@posts.to_a.last.created_at%&gt;&quot;&gt;
    &lt;%=render :partial =&gt; &quot;post&quot;, :collection =&gt; @posts%&gt;
    &lt;div id=&quot;infinite-scroll&quot;&gt;&lt;/div&gt;
  &lt;/ul&gt;
&lt;% end %&gt;
</pre></p>
<p>Now we move to the back-end, where we need to respond with new records based on that &#8216;last&#8217; timestamp attribute and remove the #infinite-scroll div case the record collection returns empty.<br />
<pre class="brush: ruby;">
###### - Model (post.rb)
class Post &lt; ActiveRecord::Base
	def self.feed(last)
		self.where(&quot;created_at &lt; ? &quot;, last).order('created_at desc').limit(5)
	end
end

###### - Controller (posts_controller.rb)
respond_to :html, :js
def index
	last = params[:last].blank? ? Time.now + 1.second : Time.parse(params[:last])
	@posts = Post.feed(last)
end

###### - View (index.js.erb)
&lt;% unless @posts.blank? %&gt;
	$('.endless_scroll_inner_wrap').append(&quot;&lt;%=escape_javascript(render :partial =&gt; 'post', :collection =&gt; @posts)%&gt;&quot;);
	$('ul').attr('last', '&lt;%=@posts.to_a.last.created_at%&gt;')
&lt;% else %&gt;
	$('#infinite-scroll').detach();
&lt;% end %&gt;
</pre></p>
<p>Notice how we append the post partial to an .endless_scroll_inner_wrap div instead of the original UL, that&#8217;s because the endless-scroll plugin creates this new div wrapping our original div whenever we scroll said div, so we need to work around that as well. The model/controller logic is pretty dull, no need to further explain that, just make sure to always pass a future timestamp when there isn&#8217;t a parameter yet so that latest (up to the second) updates will still show.</p>
<p>Well, that basically covers it, the idea behind this post is to be a quick tutorial, if you&#8217;re a Rails beginner then I highly recommend you download the entire repository code and check it out (although I pasted most of it here already for explanation&#8217;s sake). Be sure to give some feedback if you have a more robust solution, this was my first try on this subject and I&#8217;m sure more experienced developers out there must have better stuff to show :)</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pedromtavares.wordpress.com/492/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pedromtavares.wordpress.com/492/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pedromtavares.wordpress.com/492/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pedromtavares.wordpress.com/492/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pedromtavares.wordpress.com/492/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pedromtavares.wordpress.com/492/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pedromtavares.wordpress.com/492/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pedromtavares.wordpress.com/492/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pedromtavares.wordpress.com/492/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pedromtavares.wordpress.com/492/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pedromtavares.wordpress.com/492/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pedromtavares.wordpress.com/492/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pedromtavares.wordpress.com/492/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pedromtavares.wordpress.com/492/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=492&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pedromtavares.wordpress.com/2011/05/08/endless-page-scrolling-with-rails-3-and-jquery/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9ee2698da5765a84991264f0a612d661?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">pedromtavares</media:title>
		</media:content>
	</item>
		<item>
		<title>My Development Environment in 7 Items</title>
		<link>http://pedromtavares.wordpress.com/2011/01/17/my-development-environment-in-7-items/</link>
		<comments>http://pedromtavares.wordpress.com/2011/01/17/my-development-environment-in-7-items/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 01:44:50 +0000</pubDate>
		<dc:creator>pedromtavares</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>

		<guid isPermaLink="false">http://pedromtavares.wordpress.com/?p=483</guid>
		<description><![CDATA[Machine/OS I recently acquired a 13&#8243; MacBookPro which I currently work on combined with a 19&#8243; monitor that was used &#8230;<p><a href="http://pedromtavares.wordpress.com/2011/01/17/my-development-environment-in-7-items/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=483&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h1>Machine/OS</h1>
<p>I recently acquired a 13&#8243; MacBookPro which I currently work on combined with a 19&#8243; monitor that was used on my desktop machine. Working with double screens is really awesome aside the fact that I manage to lose the mouse pointer all the time and that I forget to switch apps before executing commands (causing some colateral damage), but things will get better once I get more used to it.<br />
My desktop computer also has a full work environment on a Ubuntu install case the MBP melts down, but since that&#8217;s unlikely to happen I use it only for gaming and mass file storage (can&#8217;t just leave aside 750GB of space).<br />
Aside the huge hassle of installing MySQL with Homebrew and having to manually create a root user, getting everything set on the Mac was quite easy, that is, after having to download and install XCode, of course.</p>
<h1>Editor/IDE</h1>
<p>On my desktop days I was a huge fan of a recent project called <a href="http://redcareditor.com/">RedCar</a>, which is a very light editor extremely similar to TextMate, which I now use on the Mac. I didn&#8217;t choose to stick with RedCar (since it works on all OSs) due to the fact that it crashed some times for unknown reasons, so I prefer to stick with TextMate until it&#8217;s further developed. I think the feature I liked the most about it was the Ruby syntax correction plugin, which isn&#8217;t all that relevant but avoids problems due to mistypes.</p>
<p>Recently I started reading <a href="http://ofps.oreilly.com/titles/9781449380373/">some stuff on MacRuby</a> and use XCode along with Interface Builder for it. Since everything related to Mac development integrates so well with those tools, I see no reason not to use them.</p>
<h1>Terminal</h1>
<p>My terminal is the same as it was shipped since I haven&#8217;t found the need to add any modifications to it yet, but I&#8217;m sure that&#8217;s because I haven&#8217;t come across anything that would make me feel the urge to change it.</p>
<h1>Browser</h1>
<p>Like most people, Chrome for common usage and Firefox for debugging/other development reasons (especially AJAX). I even gave Firebug for Chrome a try but it was crap, but like it or not, Chrome is way faster so I&#8217;m sticking with it.</p>
<h1>Software</h1>
<p>Four applications open at startup: Chrome, Twitter (the Twitter Mac app), <a href="http://adium.im/">Adium</a> and Skype. I eventually use Office for Mac and this free app from the App Store called Remind Me Later, which is really simple and useful.<br />
I browse the Mac App Store almost every day to find something that I truly need, and aside from the two already mentioned, I haven&#8217;t found others cool enough to be worth the cost.</p>
<h1>Source Code</h1>
<p>Not much to say, Git/GitHub for the win. I guess that&#8217;s expected from a Rails dev nowadays, huh.</p>
<h1>Music</h1>
<p>Besides not liking it much, I use iTunes since I can&#8217;t use Winamp on the Mac, but I guess (and hope) it&#8217;s a matter of getting used to. </p>
<p>Being a huge fan of psychedelic trance, I check out <a href="http://br.psyplanet.org/search/label/full%20on">PsyPlanet.org</a> almost every day (for the last 3 years) to see if anything new comes out worthy enough to get in my music selection, which, by the way, is being shared with almost 20 people through Dropbox, which in turn share their favorites too.</p>
<hr />
<p>Since this blog post was suggested to me by <a href="http://www.twitter.com/mauriciojr">@mauriciojr</a>, I now pass it on to <a href="http://www.twitter.com/diofeher">@diofeher</a>, <a href="http://www.twitter.com/jeffersongirao">@jeffersongirao</a> and <a href="http://www.twitter.com/flaviogranero">@flaviogranero</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pedromtavares.wordpress.com/483/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pedromtavares.wordpress.com/483/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pedromtavares.wordpress.com/483/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pedromtavares.wordpress.com/483/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pedromtavares.wordpress.com/483/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pedromtavares.wordpress.com/483/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pedromtavares.wordpress.com/483/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pedromtavares.wordpress.com/483/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pedromtavares.wordpress.com/483/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pedromtavares.wordpress.com/483/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pedromtavares.wordpress.com/483/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pedromtavares.wordpress.com/483/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pedromtavares.wordpress.com/483/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pedromtavares.wordpress.com/483/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=483&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pedromtavares.wordpress.com/2011/01/17/my-development-environment-in-7-items/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9ee2698da5765a84991264f0a612d661?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">pedromtavares</media:title>
		</media:content>
	</item>
		<item>
		<title>Quick Tips for the Casual jQuery Developer</title>
		<link>http://pedromtavares.wordpress.com/2010/10/23/quick-tips-for-the-casual-jquery-developer/</link>
		<comments>http://pedromtavares.wordpress.com/2010/10/23/quick-tips-for-the-casual-jquery-developer/#comments</comments>
		<pubDate>Sat, 23 Oct 2010 05:43:57 +0000</pubDate>
		<dc:creator>pedromtavares</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>

		<guid isPermaLink="false">http://pedromtavares.wordpress.com/?p=437</guid>
		<description><![CDATA[So the latest technical book I&#8217;ve been reading is Learning jQuery by Jonathan Chaffer and Karl Swedberg. The book is &#8230;<p><a href="http://pedromtavares.wordpress.com/2010/10/23/quick-tips-for-the-casual-jquery-developer/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=437&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>So the latest technical book I&#8217;ve been reading is <a href="http://www.amazon.com/Learning-jQuery-1-3-Jonathan-Chaffer/dp/1847196705">Learning jQuery</a> by Jonathan Chaffer and Karl Swedberg. The book is very interesting and comes packed with a bunch of neat little tricks that come in handy for a casual jQuery developer. With that said I decided to, again, get the most interesting parts and write them down for later referencing.</p>
<p>Unlike the book I am assuming all readers do know the basics of jQuery (thus, Javascript), so don&#8217;t expect to learn the whole thing here, and in case that&#8217;s what you were after then go search for some basic intro tutorials or buy the book. It&#8217;s worth mentioning that the book also treats about some more advanced topics such as creating shufflers, rotators, plugins, etc., but the main goal here is to be practical and know only enough necessary for our needs (thus, casual), anything above that we can always count on a number of plugins, some of which I&#8217;ll show in the end of the post.</p>
<p>For anyone willing to see any of the code that is being presented here in action, I created <a href="http://jqueryexamples.heroku.com/">a small app</a> separated into the same sections as the post containing the exact same code. Please forgive my poor design :)</p>
<p>Since this will be more of a reference guide (to myself and hopefully others) here&#8217;s a nice little quick-link menu:</p>
<ul>
<li><a href="#selectors">Selectors</a></li>
<li><a href="#traversal">DOM Traversal</a></li>
<li><a href="#events">Events</a></li>
<li><a href="#effects">Effects</a></li>
<li><a href="#plugins">Useful Plugins</a></li>
</ul>
<p><a name="selectors"><br />
<hr /></a><br />
The first and most basic thing we do on jQuery is supply a selector to the $() factory function with what we desire to manipulate, so let&#8217;s start simple with some of them:<br />
<pre class="brush: jscript;">
$('#items &gt; li:not(.sold)').addClass('highlight'); // will get all li elements directly descendant of the #items element that do NOT have the 'sold' class

$('a[href^=mailto:]').addClass('mailLink'); // will add an specific class for all links that start (^=) with 'mailto:'. The [] syntax works with any attribute;

$('a[href$=.pdf]').addClass('pdfLink'); // same as above, but gets all links ending ($=) with '.pdf'

$('tr:odd').addClass('odd'); // useful for alternating table rows, tr:even could also have been used.

$('td:contains(highlight)').addClass('highlight'); // will add the 'highlight' class to all td elements containight the 'highlight' text. This selector IS case sensitive.

$(':radio:checked').addClass('checked'); // easily handles checked radio buttons.
</pre></p>
<p>Apart from the selectors themselves, we have a method which works much like a selector, but holds the power of accepting a function and filtering results from the result of that function:<br />
<pre class="brush: jscript;">
$('a.last').filter(function(){
	return this.hostname &amp;&amp; this.hostname != location.hostname;
}).addClass('external');
</pre></p>
<p>The example above will return (and style) all links that have a domain name (excluding mailto links) and which hostnames are different than our current one, something impossible to do with the use of selectors alone.</p>
<p><a href="http://jqueryexamples.heroku.com/pages/selectors">Selectors Examples</a></p>
<p><a name="traversal"><br />
<hr /></a><br />
Although holding immense power in them, selectors sometimes aren&#8217;t enough and we need some DOM traversal methods to give us this flexibility of going up and down the DOM tree:<br />
<pre class="brush: jscript;">
$('td:contains(highlight)').next().addClass('highlight'); // will style the element right after the selected one

$('td:contains(highlight)').nextAll().addClass('highlight'); // will style ALL elements after the selected one

$('td:contains(highlight)').nextAll().andSelf().addClass('highlight'); // will style ALL elements after the selected one AND the selected one

</pre></p>
<p>The next() and nextAll() above have their counterparts prev() and prevAll(), behaving as you might expect.</p>
<p>We can also work with parents, children and siblings of an element:<br />
<pre class="brush: jscript;">
$('#some-item').parent().addClass('highlight'); // will get the element right on top of the selected element in the DOM tree

$('#categories').children().addClass('highlight-blue'); // will get all elements that come below the selected element in the DOM tree

$('#products').children('.available').addClass('highlight-blue'); // you can optionally add a selector to be more specific on what you get back.

$('#posts').siblings().addClass('highlight-green'); // will get all elements in the same level as the selected element in the DOM tree. You can also add a selector here.
</pre></p>
<p><a href="http://jqueryexamples.heroku.com/pages/traversal">DOM Traversing Examples</a></p>
<p><a name="events"><br />
<hr /></a></p>
<p>Let&#8217;s move on to events, which allow us to respond to user interactions. In jQuery we handle events quite easily by doing what we call &#8216;binding&#8217; a handler to an event on a certain element set (generated by a selector), so let&#8217;s take a look at a couple of compound method which can take two or more event handlers:<br />
<pre class="brush: jscript;">
// will highlight on the first click, then go back to normal on the second, then highlight again on the third, and so on.
$('#item').toggle(function(){
	$(this).addClass('highlight');
}, function(){
	$(this).removeClass('highlight');
});
// this will achieve the same as above
$('#item').click(function(){
	$(this).toggleClass('highlight');
}); 

// will execute the first function when the mouse is over the element, and the second one when it leaves
$('#item2').hover(function(){
	$('#item2').addClass('highlight');
}, function(){
	$('#item2').removeClass('highlight');
});
</pre></p>
<p>We could also create our custom events and attach handlers to those, binding them through the use of bind() and triggering through the use of trigger() (somewhat obvious):<br />
<pre class="brush: jscript;">
// assuming we have an outer fieldset with a bunch of text fields in it and a submit button 
$('fieldset').bind('verify', function(){
	$(this).children('input[type=text]').each(function(index,child){
		if ($(child).val().length &gt; 5){
			$(child).addClass('highlight');
		}else{
			$(child).removeClass('highlight');
		}
	});
});
//notice how we can trigger our custom events through various ways
$('#submit').click(function(){
	$('fieldset').trigger('verify');
});
$('fieldset input[type=text]').keyup(function(){
	$('fieldset').trigger('verify');
});
</pre><br />
To avoid getting caught in traps caused by <a href="http://www.quirksmode.org/js/events_order.html">event bubbling</a>, we can either control the event target by manipulating the event object itself or by simply halting event propagation:<br />
<pre class="brush: jscript;">
// assuming we have a button inside of another a div, we want to assure that the event only happens when we click on the div.
// first, using the event target
$('#outer').click(function(event){
	if (event.target == this) {
		$('#outer .button').toggleClass('hidden');
	}
});
// second, using the stopPropagation technique
$('#outer2').click(function(){
	alert('You clicked the div!');
});
$('#outer2 .button').click(function(event){
	alert('Button clicked!');
	event.stopPropagation();
});
</pre><br />
<a href="http://3dmdesign.com/development/javascript-event-delegation">Event delegation</a> is a powerful technique that should be used as often as possible and we can achieve it by assigning an outer element an event handler and using the target attribute on the event to determine what should be done:<br />
<pre class="brush: jscript;">
// assuming we have an outer #items div with alot of single items inside with ids like #item-34, #item-23, etc
$('#items').click(function(event){
	var foo = event.target.id.split('-')[0];
	if (foo == 'item'){
		alert('An item was clicked!');
	}
});
// of course we could use more simple ways to do this, but you get the catch: every item will report to the #items handler which will then decide what to do.
</pre></p>
<p>By making use of Javascript&#8217;s anonymous functions we can achieve some peculiar behavior with event handlers, such as binding and unbinding them at runtime by passing these functions as callbacks:<br />
<pre class="brush: jscript;">
var alertHandler = function(){
	alert('hi');
}
$('#some-item').click(alertHandler);
$('#some-item .sub').click(function(){
	$('#some-item').unbind('click', alertHandler);
	$(this).addClass('highlight');
});
$('#restore').click(function(){
	$('#some-item').click(alertHandler);
};
</pre><br />
<a href="http://jqueryexamples.heroku.com/pages/events">Events Examples</a></p>
<p><a name="effects"><br />
<hr /></a></p>
<p>Effects are one of the coolest parts in jQuery, with very little effort we can get some really eye-candy results. Starting some basic effect methods:<br />
<pre class="brush: jscript;">
// the peculiar thing about hide() is that it remembers the display type (block, inline, etc) before turning it to 'none', whereas show() gets that remembered value and applies it back.
$('#button').toggle(function(){
	$('#div1').hide('slow');
	$('#div2').show('slow');
}, function(){
	$('#div2').hide('slow');
	$('#div1').show('slow');
});
// now with fading
$('#button2').toggle(function(){
	$('#div3').fadeOut('slow');
	$('#div4').fadeIn('slow');
}, function(){
	$('#div4').fadeOut('slow');
	$('#div3').fadeIn('slow');
});
</pre><br />
Just like toggle() is a compound event handler, we have have slideToggle() (and most recently <a href="http://github.com/jquery/jquery/pull/56">fadeToggle()</a>) as a compount effects method:<br />
<pre class="brush: jscript;">
$('#link').click(function(){
	$('#extra').slideToggle('slow');
});
</pre><br />
Moving on to the farily complex animate() method (which I suggest you take a look at its <a href="http://api.jquery.com/animate/">documentation</a>), we can chain a bunch of animations together and get one compound result or we can queue some so they happen in the order we specify:<br />
<pre class="brush: jscript;">
// the single compount result
$('#animate').click(function(){
	$('#block').animate({height: '+=20px'}, 'slow')
	.animate({width: '+=5px'}, 'fast')
	.css('background-color', 'grey');
});
// queuing
$('#animate2').click(function(){
	$('#block2').animate({height: '+=20px'}, 'slow')
	.animate({width: '+=5px'}, 'fast')
	.queue(function(){
		$(this).css('background-color', 'grey')
		.dequeue();
	});
});
//now the coloring happens only after the width grows.
</pre><br />
Another way we could achieve this queuing is by using callbacks on animate():<br />
<pre class="brush: jscript;">
$('#animate3').click(function(){
	$('#block3').animate({height: '+=20px'}, 'slow')
	.animate({width: '+=5px'}, 'fast', function(){
		$('#block3').css('background-color', 'grey');
	});
});
</pre><br />
<a href="http://jqueryexamples.heroku.com/pages/effects">Effects Examples</a></p>
<p><a name="plugins"><br />
<hr /></a><br />
The book recommends a few very useful plugins that can handle alot of day-by-day tasks for us with quite an ease:</p>
<ul>
<li><strong><a href="http://jquery.malsup.com/form/">Form Plugin</a></strong>: makes form submition with AJAX extremely easy.</li>
<li><strong><a href="http://jqueryui.com/">jQuery UI</a></strong>: a whole library of extremely cool widgets and interaction components. </li>
<li><strong><a href="http://plugins.jquery.com/project/autocompletex">Autocomplete</a></strong>: provides a list of possible matches as the user types in a text input.</li>
<li><strong><a href="http://plugins.jquery.com/project/validate">Validation</a></strong>: a solution for client-side validation on forms.</li>
<li><strong><a href="http://plugins.jquery.com/project/maskedinput">Masked Input</a></strong>: makes it easy for users to enter data in specific formats, such as dates, phone numbers, etc.</li>
<li><strong><a href="http://plugins.jquery.com/project/tablesorter">Table Sorting</a></strong>: for client-side sorting of table data.</li>
<li><strong><a href="http://plugins.jquery.com/project/Jcrop">Jcrop</a></strong>: for client-side image cropping.</li>
<li><strong><a href="http://fancybox.net/">FancyBox</a></strong>: a cool way to add overlayed information to your page (instead of using pop-ups).</li>
<li><strong><a href="http://highcharts.com/">Highcharts</a></strong>: my personal recommendation, this is an awesome plugin for chart generation, giving you tons of options and a well spread documentation. In fact, I even recommend you <a href=""></a> taking a look at its demo page just for kicks.</li>
</ul>
<p>As for other parts of the jQuery API such as DOM manipulation and AJAX support, there wasn&#8217;t anything thats stands out enough to be worth a mention, a quick read on the documentation should be enough since all DOM manipulation methods and the standard $.ajax() method are pretty straight forward. Also, if you happen to be a Rails developer, these 2 subjects are abstracted by the use of remote form tags and RJS templates, so in most cases you wouldn&#8217;t even need to look into the jQuery documentation for this anyway.</p>
<p>That&#8217;s about it folks, if you have any other tips worth pointing out for us casual jQuery devs please comment. Cheers!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pedromtavares.wordpress.com/437/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pedromtavares.wordpress.com/437/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pedromtavares.wordpress.com/437/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pedromtavares.wordpress.com/437/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pedromtavares.wordpress.com/437/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pedromtavares.wordpress.com/437/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pedromtavares.wordpress.com/437/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pedromtavares.wordpress.com/437/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pedromtavares.wordpress.com/437/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pedromtavares.wordpress.com/437/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pedromtavares.wordpress.com/437/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pedromtavares.wordpress.com/437/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pedromtavares.wordpress.com/437/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pedromtavares.wordpress.com/437/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=437&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pedromtavares.wordpress.com/2010/10/23/quick-tips-for-the-casual-jquery-developer/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9ee2698da5765a84991264f0a612d661?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">pedromtavares</media:title>
		</media:content>
	</item>
		<item>
		<title>Notes on Behaviour Driven Development</title>
		<link>http://pedromtavares.wordpress.com/2010/08/20/notes-on-behaviour-driven-development/</link>
		<comments>http://pedromtavares.wordpress.com/2010/08/20/notes-on-behaviour-driven-development/#comments</comments>
		<pubDate>Fri, 20 Aug 2010 14:11:12 +0000</pubDate>
		<dc:creator>pedromtavares</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>

		<guid isPermaLink="false">http://pedromtavares.wordpress.com/?p=418</guid>
		<description><![CDATA[So lately I&#8217;ve been reading the beta version of the RSpec book which is supposed to come out last year, &#8230;<p><a href="http://pedromtavares.wordpress.com/2010/08/20/notes-on-behaviour-driven-development/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=418&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>So lately I&#8217;ve been reading the beta version of <a href="http://www.pragprog.com/titles/achbd/the-rspec-book">the RSpec book</a> which is supposed to come out last year, and after reading the philosophical chapter 2 that talks exclusively about <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">Behavior Driven Development</a>, I decided to take some notes and post them. Like my other reviews, I&#8217;m writing this mostly as a quick reference guide that I can check from time to time and reinforce some concepts and I suggest everyone who decides to read this to do the same.</p>
<p>First there&#8217;s an introduction on agile methodologies and how they came to be, so if you&#8217;re just interested in the BDD part, <a href="#bdd">click here</a> and jump right to it.</p>
<p>The chapter starts by mentioning how &#8216;traditional projects&#8217;, that is, those who do not apply <a href="http://en.wikipedia.org/wiki/Agile_software_development">Agile methodologies</a>, fail. Usually, it&#8217;s because of one (or more) of these reasons:</p>
<ul>
<li><strong>Delivering late or over budget</strong></li>
<li><strong>Delivering the wrong thing</strong></li>
<li><strong>Unstable in production</strong></li>
<li><strong>Costly to maintain</strong></li>
</ul>
<p>Ok, so, why? As we know most software projects go through the sequence of Planning, Analysis, Design, Code, Test and Deploy. The biggest reason for all this organization to happen is so we can avoid big changes later in development, which may screw up the whole project or at least give us a huge repairing cost. We don&#8217;t want that. So we make sure everything is &#8216;perfect&#8217; by writing gigantic sets of documents to specify what each little functionality does and that we are predicting every single detail in the system.</p>
<p>Alot of people manage to work like this and others try to improve the process by having wonderful ideas such as creating review committees and stablishing standards and whatever. Even so, mistakes do manage to get by and when something gutters up in the testing phase (where everything is supposed to be unicorns ready to go into production) such as an entire feature that was overlooked&#8230;then everyone goes mad and the whole process needs to be redone and reviewed etc etc etc.</p>
<p>As you can see, what seems to make the process <strong>not</strong> work is the way the process is being executed in the first place! We can understand why we&#8217;re taught to do things this way &#8212; people simply thought: &#8220;hey! here&#8217;s something brilliant, how about we apply the same concepts of civil engineering on software and turn it into &#8216;software engineering&#8217;?!?!&#8221;. It makes sense to spend a huge amount of time thinking about how do build an entire building before actually starting to build it, realizing that you needed an extra pillar to hold the building after getting the third floor done is not cool. The difference is that software, and I quote the book on this, &#8216;is soft&#8217;, it&#8217;s supposed to be malleable to change and not to stay the same way forever (such as a building), so you can see how we&#8217;ll be needing a redefinition of things.</p>
<p>That&#8217;s where Agile comes in. First, read the <a href="http://agilemanifesto.org/">Agile Manifesto</a>. Read it like 50 times. In short, it values &#8216;doing software&#8217; instead of mostly documenting it. One of the central principles of agil development is the use of iterations, which work like mini-projects: instead of delivering a final grand piece of software, you deliver small pieces of it as development evolves. This helps us solve those first four problems traditional projects encountered:</p>
<ul>
<li><strong>No longer</strong> delivering late or over budget: iterations help us predict how long we&#8217;re gonna take based on time spent in each iteration vs the number of iterations we defined.</li>
<li><strong>No longer</strong> delivering the wrong thing: since we&#8217;re delivering working software from time to time we can get feedback from our stakeholders and change anything that was requested with ease.</li>
<li><strong>No longer</strong> unstable in production: by delivering on each iteration we are making sure that our software is constantly working all the time.</li>
<li><strong>No longer</strong> costly to maintain: after the first iteration everything becomes maintenance, so the team is always worried about keeping everything working continuously.</li>
</ul>
<p>But not everything is marshmallows, agile development is, well, hard. Keeping a team organized enough to launch software every week or so is tense. The good news is that since agile is not a recent practice, most of its problems have answers:</p>
<ul>
<li><strong>Outcome-based planning:</strong> all we know is that everything is bound to change, so we need to find a way to estimate despite all this uncertainty.</li>
<li><strong>Streaming requirements:</strong> creating large documents of requirements won&#8217;t be able to keep up with our new delivery process, so we need a way of describing features more rapidly.</li>
<li><strong>Evolving design:</strong> with the project changing in each iteration we&#8217;ll need to always keep redesigning our software as it shapes up.</li>
<li><strong>Change existing code:</strong> as the project changes so does the code, and being able to refactor the code and add new functionalities to it without much difficulty is essencial.</li>
<li><strong>Frequent code integration:</strong> everything needs to keep working together.</li>
<li><strong>Continual regression testing:</strong> as new features are added and code is refactored we need to make sure all the work already done keeps on working and the tests keep on passing.</li>
<li><strong>Frequent production releases:</strong> all previous aspects are behaviours we can adopt ourselves, but releasing working software frequently requires co-ordination with the downstream operations team who have to keep a formally controlled environment into place. But still, we need this and if we can&#8217;t get this right then everything else doesn&#8217;t really matter because software only starts making money when in production.</li>
<li><strong>Co-located team:</strong> for everything to work you can&#8217;t afford to waste time on office bureaucracy, everybody even remotely connected to the project need to be in touch for easy communication.</li>
</ul>
<p><a name="bdd"><br />
<hr /></a><br />
And what about BDD? Well, as the book describes:</p>
<blockquote><p>Behaviour-driven development is about implementing an application by describing its behaviour from the perspective of its stakeholders.</p></blockquote>
<p>To help us understand the perspective of a stakeholder we use a technique called <a href="http://en.wikipedia.org/wiki/Domain-driven_design">Domain Driven Design</a>, and keep in mind that a &#8216;stakeholder&#8217; is <em>anyone</em> interested in the project. A huge premisse behind BDD is &#8216;writing software that matters&#8217;, which is exactly what we can acomplish from viewing this from a stakeholder&#8217;s perspective, because this way we know that what we&#8217;re doing has value. To help us focus on what&#8217;s really important, BDD follows three principles:</p>
<ul>
<li><strong>Enough is enough</strong>: simplicity, the art of maximizing the amount of work <em>not</em> done, is what we aim for.</li>
<li><strong>Deliver stakeholder value</strong>: if something is not delivering value nor is it helping you deliver value, forget about it and aim for something important (to the stakeholder!).</li>
<li><strong>It&#8217;s all behavior</strong>: whether you&#8217;re designing or coding, remember to always keep in mind that we&#8217;re dealing with behavior, it&#8217;s not about what something is, it&#8217;s what it does.</li>
</ul>
<p>Cool, we know all the theory behind BDD, and how do we apply that theory? Since BDD has major focus on stakeholders, we start from them. The first thing to do when creating a project is gathering the stakeholders and stablish a <em>vision</em> (or purpose), which will be the overall goal of the project. Of course this is something extremely high level but it keeps us reminded on what we&#8217;re aiming for in the long run. For instance, the vision of <a href="http://pedromtavares.wordpress.com/2010/07/28/batchbook-crm-integration-with-rails/">this project</a> I&#8217;m developing is to &#8220;integrate the CRM to our specific business needs&#8221;.</p>
<p>The book also uses the concept of <em>incidental stakeholders</em> which are those who will help the core stakeholder&#8217;s problem. In short, core stakeholders define a vision and incidental stakeholders help them understand what&#8217;s possible, what cost and with what likelihood. After defining the vision, we continue on working with the stakeholders to define <em>goals</em> (or outcomes), which are tangible achievments that we&#8217;ll need to address in order to know that we&#8217;ve reached our final purpose. To help keep these outcomes objective enough we could use a set of characteristics called <a href="http://en.wikipedia.org/wiki/SMART_criteria">SMART</a>, which stands for Specific, Measurable, Achievable, Relevant and Timeboxed.</p>
<p>To get to these goals we&#8217;ll need solid software, and to describe what the software will do to achieve them we use <em>feature sets</em> (or themes), which are composed of, you guessed it, features, which go down to the level in which we work on day-to-day. In a nutshell, a feature adds value to a feature set which is included in one of the goals that achieve the overall purpose of the project. This way we are certain that what we&#8217;re doing is somewhat connected to the big picture we&#8217;re trying to solve. Here&#8217;s a badly drawn diagram to show that small hierarchy:<br />
<img src="http://i18.photobucket.com/albums/b141/pmtl3000/diagram.png" /></p>
<p>In a more practical side of BDD, various roles work together to get an amount of work done, so a BDD delivery cycle would work something like this: a stakeholder and a business analyst discuss requirements in terms of features that make sense to the stakeholder (<a href="http://en.wikipedia.org/wiki/Domain-driven_design">DDD</a> helps alot here) and probably breaking them down into even smaller chunks called <em>stories</em> (which take no more than a few days work). Next the analyst talks to a tester to define the stories&#8217; scope, remembering to do just enough to get it done. Finally the developers then implement only enough to satisfy those determined scopes, and no more (this is where <a href="http://en.wikipedia.org/wiki/Test-driven_development#Test-driven_development_cycle">Red, Green, Refactor</a> comes in).</p>
<p>Getting a bit more specific on the development phase (which is the one that matters most to all of us devs anyway =P), BDD emphasizes the importance of automating these scenarios and that they should still be understandable by stakeholders (<a href="http://cukes.info/">Cucumber</a> is largely used here). The developers should focus on coding by example, which is basically TDD with a laser-sharp focus on behavior, so you write a code example by describing the behavior you want and then implement just enough code to make it work (this is where <a href="http://rspec.info/">RSpec</a>, for Rubyists, comes in) and we iterate through this process until all scenarios are done. This way we have working scenarios that we can demonstrate to the stakeholder and the story is done.</p>
<p>Since we work with stories (chunks of features) in a day-to-day basis it&#8217;s important to know deeply about them. A story is made up by 3 things:</p>
<ul>
<li><strong>Title</strong>: so we know what story we&#8217;re talking about.</li>
<li><strong>Narrative</strong>: tells us what the story is about and should at least include a type of stakeholder, benefit and a description of the feature. There are 2 formats people usually follow to narrate their stories, the first one is the Connextra format: As a |stakeholder|, I want |feature| so that |benefit|. &#8212; and a similar format that focuses more on the benefit: In order to |benefit|, a |stakeholder| wants to |feature|. </li>
<li><strong>Acceptance criteria</strong>: so we know when we are done. In the case of BDD the acceptance criteria takes form of a number of scenarios made up by individual steps. (take a look at <a href="http://cukes.info/">Cucumber</a> to get a more detailed specification on this)</li>
</ul>
<p>It&#8217;s usually a good practice to define stories before actually starting an iteration and that all the stories uses the language of the stakeholders so everyone uses a consistent vocabulary.</p>
<p>Summarizing this whole process in a nutshell: we start a project by understanding its purpose and nailing it down into smaller, doable features and then into stories and scenarios, which we automate to keep us focused on writing software that actually matters to the stakeholder. These automated scenarios become acceptance tests to ensure the application does everything we expect, and BDD thrives in supporting this model of work by making the process of automation quite easy while clearly understandable by stakeholders.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pedromtavares.wordpress.com/418/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pedromtavares.wordpress.com/418/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pedromtavares.wordpress.com/418/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pedromtavares.wordpress.com/418/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pedromtavares.wordpress.com/418/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pedromtavares.wordpress.com/418/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pedromtavares.wordpress.com/418/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pedromtavares.wordpress.com/418/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pedromtavares.wordpress.com/418/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pedromtavares.wordpress.com/418/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pedromtavares.wordpress.com/418/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pedromtavares.wordpress.com/418/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pedromtavares.wordpress.com/418/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pedromtavares.wordpress.com/418/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=418&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pedromtavares.wordpress.com/2010/08/20/notes-on-behaviour-driven-development/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9ee2698da5765a84991264f0a612d661?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">pedromtavares</media:title>
		</media:content>

		<media:content url="http://i18.photobucket.com/albums/b141/pmtl3000/diagram.png" medium="image" />
	</item>
		<item>
		<title>BatchBook CRM Integration With Rails</title>
		<link>http://pedromtavares.wordpress.com/2010/07/28/batchbook-crm-integration-with-rails/</link>
		<comments>http://pedromtavares.wordpress.com/2010/07/28/batchbook-crm-integration-with-rails/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 22:44:28 +0000</pubDate>
		<dc:creator>pedromtavares</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://pedromtavares.wordpress.com/?p=392</guid>
		<description><![CDATA[The company I currently work for recently asked me to develop an integration application (in Rails) with BatchBook, an excellent &#8230;<p><a href="http://pedromtavares.wordpress.com/2010/07/28/batchbook-crm-integration-with-rails/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=392&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://UsedCisco.com">company</a> I currently work for recently asked me to develop an integration application (in Rails) with <a href="http://www.batchblue.com/">BatchBook</a>, an excellent cloud-based <a href="http://en.wikipedia.org/wiki/Customer_relationship_management">CRM service</a>. The purpose of this integration was to adapt the CRM to our specific business needs, which require a bit more functionality than the CRM alone can offer. Fortunately they provide a <a href="http://developer.batchblue.com/">mature API</a> and an easy to use <a href="http://github.com/batchblue/batchbook">Ruby library</a>, so it&#8217;s quite simple to get started.</p>
<p>After getting used to their API and the Rails way of dealing with external objects via <a href="http://api.rubyonrails.org/classes/ActiveResource/Base.html">ActiveResource</a>, we decided to share our achievements by open-sourcing the project, which can be found on <a href="http://github.com/sdale/bblue_crm">GitHub</a>.</p>
<p>The project is an entire Rails 2.3.5 application: just download the source, configure it to integrate with your BatchBook account and you have an entire application fully integrated to BatchBook. All of the installation and configuration are explained in the <a href="http://wiki.github.com/sdale/bblue_crm/">project&#8217;s wiki</a>, along with other project technical details. </p>
<p>We split the integration process into three steps:</p>
<ol>
<li>Our first goal was to create some simple custom reporting tools. Doing so led to some overlapping functionality with the &#8216;stock&#8217; BatchBook service. Our goal here was not to recreate the features that are available in the &#8216;stock&#8217; version of BatchBook, but simply to learn the BatchBook API and extend it based on our needs.
</li>
<li>The second was to automate and combine a sequence of the tasks that simplifies the processes of our sales team. For example, converting a lead (prospect) to a customer, assigning ownership, updating tags/supertags and creating to-do&#8217;s. We are currently running a basic version of this.</li>
<li>The third and most involved task will be integrating BatchBook CRM with our custom quoting web application. Currently, BatchBook has no built-in functionality for creating traditional quotes using an inventory list of our products.<br />
We don’t want to add too many features and make it overly complex (SalesForce anyone?). Instead, we plan on building a suite of custom tools, integrated just the way we need them.</li>
</ol>
<p>On a more technical note, our application features some great performance improvements on top of Rails&#8217; ActiveResource to ease the burden of making external requests. Some of these enhancements include:</p>
<ul>
<li><strong>Object caching:</strong> the number of contacts can quickly grow, even for smaller companies. The constant stream of requests to many objects leads to awful delays. We overcame this by writing a caching system that reduces page loading time from minutes to milliseconds.</li>
<li><strong>Request limitation:</strong> a request which asks for thousands of objects is a recipe for trouble, as often it will time out. We limited the maximum number of objects per request and combined all of these in the end, preventing error pages for the end user and still getting the job done.</li>
<li><strong>Pagination:</strong> pagination is usually an easy feature to implement in a database-oriented application, but things get a bit more complicated with a service-oriented application like ours. We solved this by developing a simple pagination feature that works much like the widely-used Rails will_paginate plugin.</li>
<li><strong>Integration testing:</strong> with the help of the <a href="http://github.com/moonmaster9000/dupe">Dupe gem</a>, we wrote a test suite for our entire application to guarantee consistency and expected behavior using <a href="http://cukes.info/">Cucumber</a>.</li>
</ul>
<p>Although we developed quite a bit already, the application is still evolving as we learn more, BatchBlue extends the API and our business requirements change. This is just the start &#8211; stay tuned for upcoming features and please give us your feedback. </p>
<p>Reach us via email at <a href="mailto:feedback@usedcisco.com">feedback@usedcisco.com</a> or Twitter at <a href="http://twitter.com/usedciscodotcom">@usedciscodotcom</a> with any issues you run into or extensions you create.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pedromtavares.wordpress.com/392/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pedromtavares.wordpress.com/392/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pedromtavares.wordpress.com/392/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pedromtavares.wordpress.com/392/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pedromtavares.wordpress.com/392/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pedromtavares.wordpress.com/392/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pedromtavares.wordpress.com/392/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pedromtavares.wordpress.com/392/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pedromtavares.wordpress.com/392/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pedromtavares.wordpress.com/392/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pedromtavares.wordpress.com/392/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pedromtavares.wordpress.com/392/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pedromtavares.wordpress.com/392/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pedromtavares.wordpress.com/392/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=392&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pedromtavares.wordpress.com/2010/07/28/batchbook-crm-integration-with-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9ee2698da5765a84991264f0a612d661?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">pedromtavares</media:title>
		</media:content>
	</item>
		<item>
		<title>[DPR] &#8211; Convention Over Configuration</title>
		<link>http://pedromtavares.wordpress.com/2010/07/26/dpr-convention-over-configuration/</link>
		<comments>http://pedromtavares.wordpress.com/2010/07/26/dpr-convention-over-configuration/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 01:28:40 +0000</pubDate>
		<dc:creator>pedromtavares</dc:creator>
		
		<guid isPermaLink="false">http://pedromtavares.wordpress.com/?p=387</guid>
		<description><![CDATA[This post is part of a series of reviews on the book Design Patterns in Ruby. Check out the Introduction &#8230;<p><a href="http://pedromtavares.wordpress.com/2010/07/26/dpr-convention-over-configuration/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=387&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This post is part of a series of reviews on the book Design Patterns in Ruby. Check out the <a href="http://pedromtavares.wordpress.com/2010/07/08/dpr-introduction/">Introduction post</a> for a full table of contents along with some generic principles regarding Design Patterns.</p>
<p>Convention over configuration was a concept largely introduced by Ruby on Rails, and is certainly one of the key features of its success. The meaning behind it is simple: instead of working around some central piece of heavy configuration defined by the user, why not introduce a simple, default way to do things and put most of the configuration aside? Instead of supplying the users the ability to define a rulebook to your system, <strong>you</strong> define the rulebook when designing it, except that this rulebook is usually a set of stardands that people would follow anyway.</p>
<p>Obviously you can&#8217;t predict every single way people are gonna use your system, but you <em>can</em> predict the most simple, common cases and make those easy to work with. Of course, case a user wants something more complicated, than he can have a harder time figuring it out or configuring it himself. This concept is largely used in GUIs to favor user accessibility: in browsers you can easily mark some page as a favorite, but to, say, export those favorites to some file requires a bit more work.</p>
<p>There are a few guidelines that GUI designers follow to create easy-to-use interfaces, which the Convention Over Configuration pattern focuses on applying:</p>
<ul>
<li><strong>Anticipate needs:</strong> figure out what users do the most and make it the default way, the first paragraphs made this very clear.</li>
<li><strong>Let them say it once:</strong> design a convention that lessens the need of repetition: when people tend to always do something in a specific way, that means something, usually that it&#8217;s the right way to go, so listen and don&#8217;t ask again.</li>
<li><strong>Provide a template:</strong> conventions might be a bit overwhelming to a simple user who just wants to get started, so supply him something that he can get started and follow up on those conventions as he goes.</li>
</ul>
<p>To see all this in action, let&#8217;s develop a small application following the convention over configuration principles. To keep it simple, we want to create reports and generate them in a certain format, but we also want to make the application extendable by easily allowing other formats in.<br />
<pre class="brush: ruby;">
class Report

	def initialize(title)
		@title = title
	end

	def method_missing(name, *args)
		foo = name.to_s.split('_')
		super(name, *args) unless foo.shift == 'to'
		format_name = &quot;#{foo.first.capitalize}Format&quot;
		begin
			format_class = self.class.const_get(format_name)
			format_class.new.format(@title)
		rescue
			puts &quot;Please define #{format_name} class.&quot;
		end
	end
	
end
</pre><br />
We&#8217;re using the method_missing trick here to dynamically generate instances of formatting classes and calling the format method on them. So if I have an HtmlFormat class with a format method, to_html should make a call to it:<br />
<pre class="brush: ruby;">
class HtmlFormat
	def format(title)
		puts &quot;&lt;html&gt;&lt;body&gt;&lt;h1&gt;Header&lt;/h1&gt;&quot;
		puts &quot;&lt;p&gt;#{title}&lt;/p&gt;&quot;
		puts &quot;&lt;div class='footer'&gt;Footer&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;&quot;
	end
end

report = Report.new('My Report')
puts report.to_html
</pre><br />
As you can see, we&#8217;re defining a convention by saying that formatting classes should have the fortmat name followed by &#8216;Format&#8217;, and each of these classes should have a format method that returns a text formatted in its specific formatted name.<br />
Notice how there&#8217;s no need to configure anything: we don&#8217;t have some file telling what formats are supported and which class those formats are in, by following a convention, all this is gracefully understood by our code.</p>
<p>Suppose we wanted to add even another format, as we&#8217;ve seen, it&#8217;s as easy as naming the class right an defining a single method:<br />
<pre class="brush: ruby;">
class PlainFormat
	def format(title)
		puts &quot;Header\n\n&quot;
		puts &quot;#{title}\n\n&quot;
		puts &quot;Footer&quot;
	end
end

report = Report.new('My Report')
puts report.to_plain
</pre></p>
<p>Cool, we have all that functionality working, but its obviously not gonna be all in a single file, so we need to also organize our directory architecture by also defining a convention for it:<br />
<img src="http://i18.photobucket.com/albums/b141/pmtl3000/blog/directories.png" /><br />
Now each format class should have it&#8217;s own filename and be under the formats/ directory. Notice how this convention we&#8217;re defining is something a good engineer would do anyway.<br />
Having the directory setup, all we need is to load those files into our Report class so we don&#8217;t get requiring errors when instantiating them:<br />
<pre class="brush: ruby;">
class Report

	def initialize(title)
		@title = title
		load_formats
	end

	def method_missing(name, *args)
		foo = name.to_s.split('_')
		super(name, *args) unless foo.shift == 'to'
		format_name = &quot;#{foo.first.capitalize}Format&quot;
		begin
			format_class = self.class.const_get(format_name)
			format_class.new.format(@title)
		rescue
			puts &quot;Please define #{format_name} class.&quot;
		end
	end
	
	def load_formats
		dir = File.dirname(__FILE__)
		pattern = File.join(dir, 'formats', '*.rb')
		Dir.glob(pattern).each{|file| require file}
	end
	
end
</pre><br />
Cool, we have our whole convention setup without requiring a single piece of configuration, but we&#8217;re still missing the guideline that states we must provide a template, so let&#8217;s do that. Suppose the user doesn&#8217;t know/care what the convention is and just wants to get started he could use a scaffolding feature, supply a format as an argument and start coding format logic. Here&#8217;s a really simple way to implement that:<br />
<pre class="brush: ruby;">
format_name = ARGV[0]
class_name = format_name.capitalize + 'Format'

File.open(File.join('formats', format_name + '_format.rb'), 'w') do |f|
	f.write %Q!
class #{class_name}

	def format(title)
		#Code to format title
	end
end
	!
end
</pre><br />
With this code in a file saved as format_scaffold.rb, a call like:<br />
<pre class="brush: plain;">
ruby format_scaffold.rb xml
</pre><br />
Will generate an XmlFormat class with a format method ready to be edited.</p>
<p>As you might have noticed, this pattern, along with the DSL pattern, relies heavily on runtime evaluation of code and program introspection to work, both only possible due to Ruby&#8217;s dynamism.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pedromtavares.wordpress.com/387/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pedromtavares.wordpress.com/387/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pedromtavares.wordpress.com/387/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pedromtavares.wordpress.com/387/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pedromtavares.wordpress.com/387/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pedromtavares.wordpress.com/387/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pedromtavares.wordpress.com/387/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pedromtavares.wordpress.com/387/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pedromtavares.wordpress.com/387/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pedromtavares.wordpress.com/387/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pedromtavares.wordpress.com/387/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pedromtavares.wordpress.com/387/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pedromtavares.wordpress.com/387/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pedromtavares.wordpress.com/387/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=387&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pedromtavares.wordpress.com/2010/07/26/dpr-convention-over-configuration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9ee2698da5765a84991264f0a612d661?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">pedromtavares</media:title>
		</media:content>

		<media:content url="http://i18.photobucket.com/albums/b141/pmtl3000/blog/directories.png" medium="image" />
	</item>
		<item>
		<title>[DPR] &#8211; Metaprogramming</title>
		<link>http://pedromtavares.wordpress.com/2010/07/26/dpr-metaprogramming/</link>
		<comments>http://pedromtavares.wordpress.com/2010/07/26/dpr-metaprogramming/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 03:00:24 +0000</pubDate>
		<dc:creator>pedromtavares</dc:creator>
		
		<guid isPermaLink="false">http://pedromtavares.wordpress.com/?p=382</guid>
		<description><![CDATA[This post is part of a series of reviews on the book Design Patterns in Ruby. Check out the Introduction &#8230;<p><a href="http://pedromtavares.wordpress.com/2010/07/26/dpr-metaprogramming/">Continue reading &#187;</a></p><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=382&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This post is part of a series of reviews on the book Design Patterns in Ruby. Check out the <a href="http://pedromtavares.wordpress.com/2010/07/08/dpr-introduction/">Introduction post</a> for a full table of contents along with some generic principles regarding Design Patterns.</p>
<p>Metaprogramming is an extremely extensive subject that deserves more than a simple review like this, so for those of you more interested, check out <a href="http://pedromtavares.wordpress.com/2010/02/24/ruby-object-model-and-metaprogramming/">this blog post I made</a> about the Ruby Object Model and Metaprogramming. But let&#8217;s move on to give just a taste of what metaprogramming is all about.</p>
<p>As you have seen throughout the Ruby implementations of the GoF patterns, some things get a lot easier due to Ruby&#8217;s dynamism and metaprogramming is just one of those things that you wouldn&#8217;t even dream about doing in static typed languages. A simple usage of metaprogramming that we will explore in this review is the ability to alter the insides of a class at runtime.</p>
<p>In Ruby, instead of writing getters and setters to read/write instance variables, we call a method called attr_accessor and pass it some symbols. Turns out that we can accomplish this same feat with the use of metaprogramming. We&#8217;ll call our version &#8216;accessors&#8217;:<br />
<pre class="brush: ruby;">
class Object
	def self.accessors(*names)
		names.each do |name|
			class_eval %Q!
				def #{name}
					@#{name}
				end

				def #{name}=(val)
					@#{name} = val
				end
			!		
		end		
	end
end

class Person
	accessors :name, :age

	def initialize(name, age)
		@name = name
		@age = age
	end
end

pedro = Person.new('Pedro', 19)

puts pedro.name
puts pedro.age

pedro.name = 'Pedro Mateus Tavares'

puts pedro.name
</pre></p>
<p>In this code we directly alter the Object class to make our accessor usable by any object, then we open that class and pass it a string to evaluate into Ruby code. This way we ease the burden of people willing to use our code, of course not in this case since there already is attr_accessor, but it&#8217;s not hard to find practical uses of this.</p>
<p>A clear example is ActiveRecord, where you gain navigation through related objects simply by declaring a statement such as:<br />
<pre class="brush: ruby;">
class Post &lt; ActiveRecord::Base
	has_many :comments
end
</pre><br />
With a simple line of code we gain easy access to a post&#8217;s comments, all thanks to metaprogramming. If you&#8217;re still not convinced, I highly suggest a read at the post mentioned in the beggining of this one.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pedromtavares.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pedromtavares.wordpress.com/382/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pedromtavares.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pedromtavares.wordpress.com/382/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pedromtavares.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pedromtavares.wordpress.com/382/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pedromtavares.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pedromtavares.wordpress.com/382/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pedromtavares.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pedromtavares.wordpress.com/382/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pedromtavares.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pedromtavares.wordpress.com/382/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pedromtavares.wordpress.com/382/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pedromtavares.wordpress.com/382/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pedromtavares.wordpress.com&amp;blog=10422752&amp;post=382&amp;subd=pedromtavares&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pedromtavares.wordpress.com/2010/07/26/dpr-metaprogramming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9ee2698da5765a84991264f0a612d661?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">pedromtavares</media:title>
		</media:content>
	</item>
	</channel>
</rss>
