<?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/"
	>

<channel>
	<title>Justin Spradlin &#187; Ruby</title>
	<atom:link href="http://www.justinspradlin.com/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.justinspradlin.com</link>
	<description>Coding and such...</description>
	<lastBuildDate>Wed, 03 Mar 2010 17:52:35 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Introducing GMoney – A RubyGem for Interacting with the Google Finance API</title>
		<link>http://www.justinspradlin.com/programming/introducing-gmoney-a-rubygem-for-interacting-with-the-google-finance-api/</link>
		<comments>http://www.justinspradlin.com/programming/introducing-gmoney-a-rubygem-for-interacting-with-the-google-finance-api/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 06:00:30 +0000</pubDate>
		<dc:creator>Justin Spradlin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://www.justinspradlin.com/?p=87</guid>
		<description><![CDATA[That's why I wrote GMoney, a <a href="http://docs.rubygems.org/">RubyGem</a> for interacting with the <a href="http://code.google.com/apis/finance/">Google Finance API]]></description>
			<content:encoded><![CDATA[<div class="blockquote"> 
<p><strong>Update March 03, 2010:</strong></p><p>Due to changes in the Google Finance API only GMoney gem versions >= 0.4.3 are working.  If you run <code>gem update gmoney</code> to get the latest version or install the gem from scratch you will be fine.</p>
</div>
<p>Let&#8217;s pretend the year is 2007 and I have a close &#8220;friend&#8221; who is really excited about the upcoming <a href="http://www.fifa.com/worldcup/">2010 World Cup</a>.  My friend is not too naive and realizes that airfare to Africa, lodging, tickets to the games, and Safaris are all very expensive.  My friend has a little extra cash to save each month and with a three year time horizon he figures he can stow away a little money in a moderately aggressive mutual fund in order to take advantage of some growth opportunities.</p>
<p>Unfortunately for my friend the next two years would be some of the <a href="http://en.wikipedia.org/wiki/Financial_crisis_of_2007%E2%80%932010">worst the world economy has ever seen</a>.  Like many people, my friend <a href="http://idioms.thefreedictionary.com/took+a+bath#MainTxt">took a bath</a> on his investments and his hopes and dreams of going to the World Cup went down the drain along with his money.</p>
<p>It&#8217;s too bad my friend didn&#8217;t keep better track of his investments.  Perhaps if he had he could have pulled his money out of the stock market and salvaged his vacation.  Since my friend is an avid Ruby lover I figured I&#8217;d help make sure he doesn&#8217;t end up in this situation ever again.  That&#8217;s why I wrote GMoney, a <a href="http://docs.rubygems.org/">RubyGem</a> for interacting with the <a href="http://code.google.com/apis/finance/">Google Finance API</a>.</p>
<span id="more-87"></span>
<h3>Background</h3>
<p>The Google Finance API allows users to interact with <a href="http://www.google.com/finance">Google Finance</a> and can help developers programmatically &#8220;request a list of a user&#8217;s portfolios, retrieve performance and return statistics on an existing portfolio, query the positions and transactions in a portfolio, and create new portfolios and transactions.&#8221;</p>
<p>GMoney is a wrapper for this API and allows developers to take advantage of the API&#8217;s functionality using the <a href="http://www.ruby-lang.org/en/">Ruby programming language</a>.  To minimize the learning curve I tried to give GMoney an interface similar to that of <a href="http://ar.rubyonrails.org/">ActiveRecord</a> so that developers would have a familiar starting point.</p>
<h3>Google Finance Model</h3>
<p>The Google Finance model is pretty simple.  It is made up of the following three entities:</p>
<p><strong>Portfolios</strong></p>
<div class="blockquote"> 
<p>A portfolio is a collection of positions that the user holds in various securities, plus metadata.  Each portfolio entry contains the portfolio&#8217;s title along with data such as currency and total market value. Each portfolio entry also contains a link to the portfolio&#8217;s position feed (i.e. a Portfolio &#8220;has_many&#8221; Positions).</p>
</div>
<p><strong>Positions</strong></p>
<div class="blockquote"> 
<p>A position is a collection of information about a security that the user holds.  Each position entry contains the ticker exchange and symbol for a stock, mutual fund, or other security, along with the number of units of that security that the user holds. Each position entry also contains a link to the position&#8217;s transaction feed (i.e. a Position &#8220;has_many&#8221; Transactions).</p>
<p>You can&#8217;t directly create or update position entries; positions are derived from transactions.</p>
</div>
<p><strong>Transactions</strong></p>
<div class="blockquote"> 
<p>A transaction is a collection of information about an instance of buying or selling a particular security.  Each transaction entry contains a transaction type (such as buy or sell), a number of units, the price, and so on.</p>
</div>
<h3>Installation</h3>
<p>To install GMoney simply run the following command:</p>
<div class="codeBlock"> 
	<pre><code>gem install gmoney</code></pre> 
</div> 
<h3>Login</h3>
<p>You will need a <a href="http://www.google.com/accounts">Google account</a> in order to use the Google Finance API.  Once you have obtained an account you can login via GMoney using the following code:</p>
<div class="codeBlock"> 
	<pre><code>require 'rubygems'
require 'gmoney'

GMoney::GFSession.login('&lt;YOUR GOOGLE USER ID&gt;','&lt;YOUR GOOGLE PASSWORD&gt;')</code></pre> 
</div>
<h3>Create a portfolio</h3>
<p>If you were to login to Google Finance for the first time using a browser you would see the following screen showing the default Google Finance Portfolio called &#8220;My Portfolio&#8221;:</p>
<p><a href="http://www.justinspradlin.com/images/default_portfolio.jpg"><img src="http://www.justinspradlin.com/images/default_portfolio_s.jpg" class="center" alt="Create Portfolio" /></a></p>
<p>To create your own Portfolio using GMoney use the following code:</p>
<div class="codeBlock"> 
	<pre><code>portfolio = GMoney::Portfolio.new
portfolio.title = "My New Ruby Portfolio"
portfolio.save</code></pre> 
</div>
<p>After executing the code and refreshing the browser you should see that the &#8220;My New Ruby Portfolio&#8221; has been created.</p>
<p><a href="http://www.justinspradlin.com/images/create_portfolio.jpg"><img src="http://www.justinspradlin.com/images/create_portfolio_s.jpg" class="center" alt="Create Portfolio" /></a></p>
<h3>Create a transaction(s)</h3>
<p>As mentioned above transactions are used to buy and sell stocks within a given portfolio.  The positions within your portfolio will be based on the transaction information.  Running the following code will buy shares of Apple, Red Hat, Google, and Microsoft and place them into your portfolio:</p>
<div class="codeBlock"> 
	<pre><code>stocks = {"NASDAQ:GOOG" => 529.00, 
          "NASDAQ:AAPL" => 192.00, 
          "NYSE:RHT" => 27.00, 
          "NASDAQ:MSFT" => 28.00}
 
stocks.each do |symbol, price| 
  transaction = GMoney::Transaction.new
  #pid is the human readable id of the portfolio created above
  transaction.portfolio = portfolio.pid
  transaction.type = GMoney::BUY
  transaction.shares = 50
  transaction.ticker = symbol
  transaction.price = price  
  transaction.save
end</code></pre> 
</div>
<p>The result of running the code is as follows:</p>
<p><a href="http://www.justinspradlin.com/images/buy_stocks.jpg"><img src="http://www.justinspradlin.com/images/buy_stocks_s.jpg" class="center" alt="Create Portfolio" /></a></p>
<h3>Update Transaction</h3>
<p>If you actually meant to buy 100 shares of Goolge instead of 50 you can update the transaction using the following code:</p>
<div class="codeBlock"> 
	<pre><code>#I know the transaction id is '4'
transaction = GMoney::Transaction.find "#{portfolio.pid}/NASDAQ:GOOG/4"
transaction.shares = 100
transaction.save</code></pre> 
</div>
<p>The result:</p>
<p><a href="http://www.justinspradlin.com/images/update_goog.jpg"><img src="http://www.justinspradlin.com/images/update_goog_s.jpg" class="center" alt="Create Portfolio" /></a></p>
<h3>Delete Transaction</h3>
<p>We can delete a transaction like so:</p>
<div class="codeBlock"> 
	<pre><code>GMoney::Position.find("#{portfolio.pid}/NASDAQ:MSFT").delete</code></pre> 
</div>
<p>Now we have no more MSFT stock:</p>
<p><a href="http://www.justinspradlin.com/images/delete_trans.jpg"><img src="http://www.justinspradlin.com/images/delete_trans_s.jpg" class="center" alt="Create Portfolio" /></a></p>
<h3>Reading all the Positions in a Porfolio</h3>
<p>If we&#8217;d like to see all of the positions within our portfolio we can execute this code:</p>
<div class="codeBlock"> 
	<pre><code>portfolio.positions.each do |position| 
  puts position.title
end</code></pre> 
</div>
<p><strong>Output:</strong></p>
<div class="outputBlock"> 
<pre>Red Hat, Inc.
Apple Inc.
Google Inc.</pre> 
</div> 
<h3>Gotcha</h3>
<p>There is a bit of a &#8220;gotcha&#8221; right now with the Google Finance API.  For whatever reason, stock returns information is not being sent by Google.  I figured it was something I was doing wrong in my code, but then I used <a href="http://code.google.com/apis/gdata/docs/client-libraries.html">Google&#8217;s official API client</a> and was still unable to retrieve the returns data.  I&#8217;ll be sure to file a <a href="http://code.google.com/p/gdata-issues/issues/list">bug report</a> with Google over the next few days.</p>
<h3>Conclusion</h3>
<p>GMoney offers a lot more features than what has been written about here.  Be sure to check out the documentation and the source code on <a href="http://github.com/jspradlin/gmoney">Github</a>.  The full script of the code used for this blog entry can also be found on <a href="http://github.com/jspradlin/justinspradlin.com-blog-examples/tree/master/2010-02-01_Introducing-GMoney-A-RubyGem-for-Interacting-with-the-Google-Finance_API/">Github</a>.</p>
<p>Overall building GMoney was an incredible learning experience.  It was my first significant Ruby project and also my first Open Source project.  As of today GMoney has been downloaded almost <a href="http://gemcutter.org/gems/gmoney">200 times</a>.  I&#8217;ve tested GMoney on Windows and Linux using Ruby versions 1.8.6, 1.8.7, and 1.9.1 (via <a href="http://rvm.beginrescueend.com/">RVM</a>).  Feedback and bug reports are more than welcome.</p>
<p>With GMoney in place my friend will be sure to keep much better track of his investments and is looking forward to the <a href="http://en.wikipedia.org/wiki/2014_FIFA_World_Cup">2014 World Cup in Brazil</a>.</p>
<p><i>Disclaimer:</i> I am in no way endorsing any of the companies mentioned in this blog entry and all company references are for example purposes only.</p>]]></content:encoded>
			<wfw:commentRss>http://www.justinspradlin.com/programming/introducing-gmoney-a-rubygem-for-interacting-with-the-google-finance-api/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Giving Design Patterns a Second Chance: Ruby Edition</title>
		<link>http://www.justinspradlin.com/reviews/giving-design-patterns-a-second-chance-ruby-edition/</link>
		<comments>http://www.justinspradlin.com/reviews/giving-design-patterns-a-second-chance-ruby-edition/#comments</comments>
		<pubDate>Thu, 02 Jul 2009 00:00:28 +0000</pubDate>
		<dc:creator>Justin Spradlin</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Reviews]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.justinspradlin.com/?p=27</guid>
		<description><![CDATA[I have a confession to make.
You know that really popular design patterns book that most software developers (especially in the Java world) claim to have read?  You know the one I&#8217;m talking about. The one written by the &#8220;Gang of Four&#8221;.  The one you were supposed to have read during your junior or [...]]]></description>
			<content:encoded><![CDATA[<a href="http://www.justinspradlin.com/reviews/giving-design-patterns-a-second-chance-ruby-edition/"><img class="rev_right" src="http://www.justinspradlin.com/images/dpir2.jpg" alt="Design Patterns in Ruby" /></a><p>I have a confession to make.</p>
<p>You know that really popular design patterns book that most software developers (especially in the Java world) claim to have read?  You know the one I&#8217;m talking about. The one written by the &#8220;Gang of Four&#8221;.  The one you were supposed to have read during your junior or senior year of college.  Yeah, <a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612">this one</a>.</p>
<p>I&#8217;ve never read it.</p>
<p>Sure, I&#8217;ve owned it.  I have even thumbed through it a few times.  But I&#8217;ve never sat down with any real intention of absorbing the information within its covers.  The problem for me personally was that when I first opened <em>Design Patterns</em> I was just starting my software development career.  I was too young and hadn&#8217;t seen enough code to really comprehend the authors&#8217; message or understand the need for such a book.</p>
<p><span id="more-27"></span></p>
<p>A few years have passed since then and while it&#8217;s still early in my career I now have a much better idea of how to develop software and have a much better understanding of Object Oriented Design.  Even though I spend a significant amount of my free time developing my skills and reading about software development I have yet to read the seminal <em>Design Patterns</em> book.</p>
<p>Design patterns have left a bad taste in my mouth.  Over the years they have been abused and misunderstood.  They seem to have become caught up in the all too familiar silver bullet buzzword vernacular of the IT industry (<a href="http://en.wikipedia.org/wiki/Service_Oriented_Architecture">SOA</a> anyone?).  So I simply avoided them.  Unless I was about to interview for a new job, design patterns never so much as crossed my mind.  Repeat after me: Singleton, Factory, MVC.  <em>You&#8217;re hired!</em></p>
<p>But things have changed.  Over the past year and a half or so I&#8217;ve really started to focus on my career as a software developer.  I&#8217;ve learned new operating systems and languages, created this blog, and started attending local developer meetings on a regular basis.  While I still have my favorite technologies and interests, I&#8217;ve been doing a much better job of keeping an open mind about trying out new development tools and methodologies.</p>
<p>Enter <a href="http://jroller.com/rolsen/">Russ Olsen</a>.  In addition to being a great developer and all around good guy, Russ is someone who I had the honor of working with at the beginning of my career.  He was very much a mentor and I credit him with teaching me many of the applied fundamentals of software development.  So what does Russ have to do with design patterns?  Well it just so happens that a few years after I left the company where Russ and I worked together he wrote a book called <em><a href="http://www.amazon.com/Design-Patterns-Ruby-Russ-Olsen/dp/0321490452">Design Patterns in Ruby</a></em>.  Because of my respect for Russ and my fondness of Ruby I decided I&#8217;d give the book a shot.  While I was certainly expecting to learn some new things, I was surprised (although I shouldn&#8217;t have been) by how much great information I was able to extract from this book.</p>
<p>In their most minimal form, design patterns are simply reusable solutions that have been created to solve common coding problems.  While this may seem intuitive, it was actually somewhat of a revelation to me – a person who has ignored the direct usage of design patterns for all these years.  I see now that given an appropriate situation design patterns can be used to create consistent, maintainable code.  The important thing to remember is that each pattern has a specific use and should only be used when applicable.</p>
<p>Although the title of the book is <em>Design Patterns in Ruby</em>, a majority of the principles and patterns apply to many other object oriented languages as well.  In fact, while I was reading Russ&#8217;s book I was in the middle of working on a small Java project.  This project had to keep track of rapid state changes on a particular website.  I needed to keep track of a countdown timer, a list of participants, and an aggregate score.  Each of these pieces of information was updated independently, but I needed to make decisions in my code based on the combination of this information at any given time.  After reading the chapter on the <a href="http://en.wikipedia.org/wiki/Observer_pattern">Observer pattern</a>, I realized it would be the perfect fit.  Prior to using the pattern my code was a huge pile of tangled spaghetti. Afterwards, it was clean and easy to read.</p>
<p>I really liked the way the chapters were organized in <em>Design Patterns in Ruby</em>.  Russ started each chapter by posing a common programming problem.  Then he would explain how a specific design pattern could be used to solve that problem.  As the chapter progressed Russ would work through the problem using examples that were very easy to understand.  Each chapter ended with real world examples of the patterns as they have been implemented in the Ruby core libraries or various open source projects.  I found the real world code samples to be especially useful as compliments to the examples given in the book.</p>
<p>Not only did I enjoy reading this book because it was written by Russ, but I genuinely feel like it has helped to make me a better programmer.  In addition, it has helped increase my Ruby specific programming skills.  Learning to program in Ruby is easy, but learning to program the &#8220;Ruby Way&#8221; is a much greater challenge.  Ruby is full of powerful idioms that are not necessarily obvious without a deep examination of the language.  Russ&#8217;s book helps enlighten would be Ruby programmers to many of Ruby&#8217;s powerful language features.</p>
<p>For example, compare an implementation of the <a href="http://en.wikipedia.org/wiki/Proxy_pattern">Proxy pattern</a> written in Java and Ruby:</p>
<h3>Java Version</h3>
<p><code>MathService.java</code></p>
<div class="codeBlock">
<pre><code>public interface MathService {
    public void add(int x, int y);
    public void subtract(int x, int y);
}</code></pre>
</div>
<p><code>MathServiceImpl.java</code></p>
<div class="codeBlock">
<pre><code>public class MathServiceImpl implements MathService {
    public void add(int x, int y) {
        System.out.println("Result ("+x+ " + "+y+"): " + (x + y));
    }

    public void subtract(int x, int y) {
        System.out.println("Result ("+x+ " - "+y+"): " + (x - y));
    }
}</code></pre>
</div>
<p><code>MathServiceProxy.java</code></p>
<div class="codeBlock">
<pre><code>public class MathServiceProxy implements MathService {
    private MathService delegate;

    public MathServiceProxy(MathService ms){
        this.delegate = ms;
    }

    public void add(int x, int y) {
        System.out.println("Call made to the add method");
        delegate.add(x, y);
    }

    public void subtract(int x, int y) {
        System.out.println("Call made to the subtract method");
        delegate.subtract(x, y);
    }
}</code></pre>
</div>
<p><code>MathServiceDriver.java</code></p>
<div class="codeBlock">
<pre><code>public class MathServiceDriver {
    public static void main(String[] args) {
        MathService ms = new MathServiceProxy(new MathServiceImpl());
        ms.add(1, 2);
        ms.subtract(4, 3);
    }
}</code></pre>
</div>
<h3>Ruby Version</h3>
<p><code>math_service.rb</code></p>
<div class="codeBlock">
<pre><code>class MathService
  def add(x, y)
    puts "Result (#{x} + #{y}): #{x + y}"
  end

  def subtract(x, y)
    puts "Result (#{x} - #{y}): #{x - y}"
  end
end

class MathServiceProxy
  def initialize(math_service)
    @delegate = math_service
  end

  def method_missing(name, *args)
    puts "Call made to the #{name} method"
    @delegate.send(name, *args)
  end
end

ms = MathServiceProxy.new(MathService.new)
ms.add(1,2)
ms.subtract(4,3)</code></pre>
</div>
<h3>Result of Running Either Program</h3>
<div class="outputBlock">
<pre>Call made to the add method
Result (1 + 2): 3
Call made to the subtract method
Result (4 - 3): 1</pre>
</div>
<p>In this example we use the Proxy pattern to print out a message before each method call.  If we decided to add any methods to our <code>MathService</code> interface we would need to update our <code>MathServiceImpl</code> and <code>MathServiceProxy</code> Java classes as well.  However, by using Ruby&#8217;s built in <code>method_missing</code> method we have the ability to wrap each <code>MathService</code> method call dynamically without having to write a new method in our <code>MathServiceProxy</code> class.  Ruby removes the tedium of implementing the Proxy pattern.</p>
<p>This is just one small example of the flexibility and power provided by the Ruby language.  Before reading Russ&#8217;s book I didn&#8217;t necessarily &#8220;get&#8221; many of Ruby&#8217;s idioms.  Reading <em>Design Patterns in Ruby</em> has certainly helped solidify my understanding and is great for programmers who would like to take their Ruby skills to the next level.<!--end_raw--></p>
<h3>Code Samples</h3>
<p>All code samples from this blog entry can be downloaded from GitHub by <a href="http://github.com/jspradlin/fiascode-blog-examples/tree/8b744699647d587329f0b7e2f558360c67426173/2009-07-01_Giving-Design-Patterns-a-Second-Chance-Ruby-Edition">clicking here</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.justinspradlin.com/reviews/giving-design-patterns-a-second-chance-ruby-edition/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ruby Screen Scraping with scRUBYt!</title>
		<link>http://www.justinspradlin.com/programming/ruby-screen-scraping-with-scrubyt/</link>
		<comments>http://www.justinspradlin.com/programming/ruby-screen-scraping-with-scrubyt/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 10:00:21 +0000</pubDate>
		<dc:creator>Justin Spradlin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.justinspradlin.com/?p=26</guid>
		<description><![CDATA[I am currently in the market to buy my first home so I've been spending a lot of time on various real estate websites searching through listings trying to find the perfect property.  I live in a competitive housing market so it is important that I am informed whenever a new property becomes available. [...]]]></description>
			<content:encoded><![CDATA[<p>I am currently in the market to buy my first home so I've been spending a lot of time on various real estate websites searching through listings trying to find the perfect property.  I live in a competitive housing market so it is important that I am informed whenever a new property becomes available.  Logging onto any number of real estate websites to check for new listings each day is very repetitive and time consuming.  Fortunately, it is possible to easily gather this information automatically using a technique called <a href="http://en.wikipedia.org/wiki/Screen_scraping">screen scraping</a>.</p>
<p>Since most web pages are simply made of HTML it is easy for a computer to parse and store the information contained within these documents.  Each programming language commonly has a host of libraries to assist in the screen scraping/parsing process and Ruby is no exception.  To create simple screen scrapers in Ruby I have been using a library called <a href="http://scrubyt.org/">scRUBYt!</a>.  scRUBYt! provides methods to access a given website and scrape its content.  All the programmer needs to do is provide the <a href="http://www.w3.org/TR/xpath">XPath</a> string to the desired information.</p>
<p>Using the scRUBYt! library has allowed me to write a small screen scraper script to access the <a href="http://franklymls.com/">FranklyMLS.com</a> website, check for new listings, and then report back with the results. This has saved me a lot of time and effort.  Let's dive into some code to see how this is done.</p>
<span id="more-26"></span>
<p>First, we'll need to create a simple class to store the information that we scrape from the FranklyMLS.com website.  The <code>Property</code> class will hold various property related information (price, MLS number, square footage, etc.):</p>
<div class="codeBlock">
	<pre><code>class Property
  attr_accessor :mls, :list_price, :dom, :address,
                :city, :zip, :bed, :bath, :sqft, :built

  def initialize(property)
    @mls = (property/:mls).inner_html
    @list_price = (property/:list_price).inner_html
    @dom = (property/:dom).inner_html
    @address = (property/:address).inner_html
    @city = (property/:city).inner_html
    @zip = (property/:zip).inner_html
    @bed = (property/:bed).inner_html
    @bath = (property/:bath).inner_html
    @sqft = (property/:sqft).inner_html
    @built = (property/:built).inner_html
  end
end</code></pre>
</div>
<p>Next we'll need to make sure that scRUBYt! is installed.  If you don't already have <a href="http://github.com/">Github</a> set up as one of your gem repositories do so now by executing the following command:</p>
<div class="codeBlock">
	<pre><code>gem sources -a http://gems.github.com</code></pre>
</div>
<p>Then install the scRUBYt! gem:</p>
<div class="codeBlock">
	<pre><code>gem install jspradlin-scrubyt</code></pre>
</div>
<p><i><strong>Side note:</strong>  I've built some functionality into the scRUBYt! library so you will need to grab the gem from <a href="http://github.com/jspradlin">my Github repository</a> (i.e. jspradlin-scrubyt).  I've spoken with the lead developer on the scRUBYt! project and it looks like my changes might make it into a future version of the official gem.</i></p>
<p>At this point we need to give scRUBYt! the URL of a website that we wish to scrape.  The FranklyMLS.com website has its own special URL query syntax which displays only properties that meet our specific criteria.  For example, if we only wanted to find active listings in the following zip codes - 22201, 22202, 22203 - the FranklyMLS.com URL would be:</p>
<div class="codeBlock">
	<pre><code>http://franklymls.com/default.aspx?m=R&amp;s=(22201,22202,22203)+active</code></pre>
</div>
<p>We can dynamically generate a URL with our specific housing criteria by including the following code in our script:</p>
<div class="codeBlock">
	<pre><code># Generate the URL for FranklyMLS.com given
# the following criteria:
zips = [22201,22202,22203,22209]
beds = [2, 3].collect{ |bed| bed.to_s+'bdr'}
min_price = 150 #in thousands
max_price = 350 #in thousands
exclusions = ['JEFFERSON'].collect{ |exclude| "+-#{exclude}"}

fmls_url = "http://franklymls.com/default.aspx?"
fmls_url += "m=R&amp;l=#{min_price}K&amp;h=#{max_price}K"
fmls_url += "&amp;s=(#{zips.join(',')})+active"
fmls_url += "+(#{beds.join(',')})"
fmls_url += exclusions.to_s</code></pre>
</div>
<p>Now we're ready to scrape some housing data.  Once the FranklyMLS.com property page loads we are presented with a table that contains information about the listings that meet our criteria (image modified to save space):</p>
<img class="centered" src="http://www.justinspradlin.com/images/table.jpg" alt="FranklyMLS.com Property Table"/>
<p>The HTML that generates this table would appear like this (modified to save space):</p>
<div class="codeBlock">
	<pre><code><span class="colorBlue">&lt;table id="dgRealtorStyle"&gt;</span>
  ...
  <span class="colorGreen">&lt;tr style="display:visible"&gt;</span>
    <span class="colorRed">&lt;td&gt;&lt;a&gt;...&lt;/a&gt;&lt;a&gt;AR6552162&lt;/a&gt;&lt;/td&gt;&lt;!-- td[1]--&gt;</span>
    <span class="colorPurple">&lt;td&gt;$256,000&lt;/td&gt;&lt;!-- td[2]--&gt;</span>
    &lt;td&gt;$339,000&lt;/td&gt;
    &lt;td&gt;$&lt;/td&gt;
    &lt;td&gt;&nbsp;&lt;/td&gt;
    &lt;td&gt;&nbsp;&lt;/td&gt;
    &lt;td&gt;562&lt;/td&gt;
    <span class="colorOrange">&lt;td&gt;1931 CLEVELAND #313&lt;/td&gt;&lt;!-- td[8]--&gt;</span>
    ...
    &lt;td&gt;ARLINGTON&lt;/td&gt;
    &lt;td&gt;22201&lt;/td&gt;
    &lt;td&gt;&nbsp;&lt;/td&gt;
    &lt;td&gt;CLEVLAND HO&lt;/td&gt;
    &lt;td&gt;3/1&lt;/td&gt;
    &lt;td&gt;860&lt;/td&gt;
    &lt;td&gt;1960&lt;/td&gt;
    &lt;td&gt;...&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;160&lt;/td&gt;
    &lt;td&gt;&lt;a&gt;x&lt;/a&gt;&lt;/td&gt;
  <span class="colorGreen">&lt;/tr&gt;</span>
  ...
<span class="colorBlue">&lt;/table&gt;</span></code></pre>
</div>
<p>Finally, the Ruby code to scrape this data using scRUBYt!:</p>
<div class="codeBlock">
	<pre><code>#Scrape the FranklyMLS.com website using scRUBYt!
property_data = Scrubyt::Extractor.define do
  fetch fmls_url

  <span class="colorBlue">properties '//table[@id="dgRealtorStyle"]'</span> do
    <span class="colorGreen">property "//tr"</span> do
      <span class="colorRed">mls "/td[1]//a[2]"</span>
      <span class="colorPurple">list_price "/td[2]"</span>
      dom "/td[7]"
      <span class="colorOrange">address "/td[8]"</span>
      city "/td[9]"
      zip "/td[10]"
      bed "/td[13]",
        :format_output => lambda {|bed_bath| bed_bath.split('/')[0]}
      bath "/td[13]",
        :format_output => lambda {|bed_bath| bed_bath.split('/')[1]}
      sqft "/td[14]"
      built "/td[15]"
    end
  end
end</code></pre>
</div>
<p>If you look at the table, the HTML code, and the Ruby code you'll see that I've color coordinated each separate piece of information to illustrate how it is parsed and then stored.  The scRUBYt! library will "fetch" the given URL, locate the HTML elements by the given XPath, and then store the data.</p>
<p>Once we have all of the data collected we may want to do something useful with the information such as convert it into an <a href="http://en.wikipedia.org/wiki/RSS_(file_format)">RSS</a> feed.  We can accomplish this by using the <a href="http://wiki.github.com/why/hpricot">Hpricot</a> and <a href="http://builder.rubyforge.org/">Builder</a> libraries (which should be installed as dependencies of scRUBYt!).  The code for the RSS conversion would look like this:</p>
<div class="codeBlock">
	<pre><code># Read in the XML generated by scRUBYt! then
# convert the data into Property objects
# and store them in the property_hash.
property_hash = {}

hp = Hpricot.XML(property_data.to_xml)
(hp/:property).each do |property|
  property_hash[(property/:mls).inner_html] = Property.new(property)
end

# Using the Builder library, iterate through
# the property_hash to generate an RSS feed.
xml = Builder::XmlMarkup.new(:target => $stdout, :indent => 2 )
xml.instruct! :xml, :version => "1.0"
xml.rss :version => "2.0" do
  xml.channel do
    xml.title "Property Feed"
    xml.link "&lt;--YOUR URL--&gt;"
    xml.description "This is my property feed"

    property_hash.each do | key, property |
      pub_date = (Time.now - property.dom.to_i*60*60*24)
      pub_date = pub_date.strftime("%a, %d %b %Y %I:%M:%S")

      xml.item do
        xml.title property.address
        xml.link "http://franklymls.com/#{property.mls}"
        xml.pubDate "#{pub_date} EST"
        xml.description "City: #{property.city}
          Address: #{property.address}
          Price: #{property.list_price}
          Bed: #{property.bed}
          Bath: #{property.bath}
          Sqft: #{property.sqft}
          Built: #{property.built}"
      end
    end
  end
end</code></pre>
</div>
<p>To make sure I get routine updates, I run this Ruby code on my server every hour using a <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> and pipe its output to an RSS feed.  I am subscribed to the generated RSS feed so now I know exactly when a new property becomes available in my area!</p>
<p>Overall scRUBYt! is very easy to use and for simple screen scraping tasks it should work fine.  However, I have found that it can run into some problems when the HTML gets complex.  In these cases I would recommend using Hpricot for fine-level scraping.</p>
<p>To view the source code for this entry and to view other screen scraping code that I have written check out <a href="http://github.com/jspradlin">my Github page</a>.</p>
<p>If you'd like to look at another example of scRUBYt! in action, feel free to read the post I wrote for my company's blog by <a href="http://blog.platinumsolutions.com/Ruby-Screen-Scraping-and-a-Little-Friendly-Competition">clicking here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.justinspradlin.com/programming/ruby-screen-scraping-with-scrubyt/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Ruby Nation: Day 2 Wrap Up</title>
		<link>http://www.justinspradlin.com/general/ruby-nation-day-2-wrap-up/</link>
		<comments>http://www.justinspradlin.com/general/ruby-nation-day-2-wrap-up/#comments</comments>
		<pubDate>Sun, 03 Aug 2008 22:49:25 +0000</pubDate>
		<dc:creator>Justin Spradlin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.justinspradlin.com/?p=18</guid>
		<description><![CDATA[
Opening Keynote - Rich Kilmer
Rich Kilmer's opening keynote was by far the best presentation of the day.  Rich is an incredibly experienced and skilled Ruby developer who was one of the earlier adopters of the language.  During his keynote, Rich walked through his experiences with Ruby dating all the way back to 2001. [...]]]></description>
			<content:encoded><![CDATA[<p></p>
<h3>Opening Keynote - Rich Kilmer</h3>
<p>Rich Kilmer's opening keynote was by far the best presentation of the day.  Rich is an incredibly experienced and skilled Ruby developer who was one of the earlier adopters of the language.  During his keynote, Rich walked through his experiences with Ruby dating all the way back to 2001.  He has certainly worked on some interesting projects for impressive government agencies including DARPA and the United State Air Force.  Rich also talked about projects he has created for the Ruby community including <a href="http://freeride.rubyforge.org/wiki/wiki.pl">FreeRIDE</a> - a Ruby IDE and <a href="http://rubyforge.org/">RubyForge</a> - a code repository for Ruby projects.</p>
<p>One particularly interesting thing Rich mentioned was that Ruby is becoming a mainstream language.  I personally find this both exciting and scary.  It is exciting that the community is growing at that there will likely be more opportunities to work on Ruby projects professionally, but it is a bit worrisome that the community could start to be overpopulated with run-of-the-mill developers transitioning from other dying mainstream languages.</p>
<span id="more-18"></span>
<h3>Ruby Puzzlers - Mike Furr</h3>
<p>Mike Furr, a doctoral student at <a href="http://www.umd.edu/">UMCP</a>, gave a presentation on edge case scenarios that occur in the Ruby language.  Since I'm pretty new to Ruby I struggled to follow along, but Mike did do a good job of explaining how Ruby code reacted under various situations.  Even though it can be rare to deal with edge cases in a language, it is nice to know how to avoid them or work your way out of them if they do arise.</p>
<h3>Practical JRuby - David Keener</h3>
<p>A Java(ish) presentation at a Ruby conference?  It may seem a bit strange at first, but it actually makes a lot of sense.  Java as a platform has some pretty rock solid features including performance, garbage collection, and concurrency.  A lot time and thought has also been invested into Java libraries and corporate infrastructure so in many ways it makes sense to take advantage of what is already available.  David Keener hit on all of these points in his presentation and gave an example of how to integrate <a href="http://jruby.codehaus.org/">JRuby</a> with the <a href="http://www.jfree.org/jfreechart/">JFreeChart</a> Java library.</p>
<h3>Tools for Your Ruby Toolbox - Dave Bock</h3>
<p>Dave Bock is another <a href="http://www.fgm.com">FGM</a> employee that I had the pleasure of working with a few years back.  Dave has since moved on and started his own shop called <a href="http://www.codesherpas.com/">Codesherpas</a>.  In his presentation, Dave talked about 3 lightweight tools that can be used to quickly accomplish tasks in Ruby.  Dave first talked about <a href="http://www.rubyinside.com/staticmatic-ruby-powered-static-web-site-system-603.html">StaticMatic</a>, a framework for developing simple static websites using templates, but without using all of the built in functionality of Rails.  Another web framework Dave talked about was <a href="http://sinatrarb.com/Home">Sinatra</a>.  Again, this framework allows developers to create simple web applications without the full Rails stack, but it also includes some RESTful functionality.  Finally, Dave talked about <a href="http://www.ruby-doc.org/stdlib/libdoc/gserver/rdoc/classes/GServer.html">GServer</a>, a generic server library that allows developers to easily create server applications of their own.  During his presentation Dave demoed a quick "Knock Knock" client he created using the GServer library.</p>
<h3>Lightning Talks</h3>
<p>There were five lightening talks given yesterday, but again <a href="http://smartic.us/">Bryan Liles</a> stole the show with his presentation on Project Management.  The basic takeaway: meet with your reports regularly, project confidence, and set up processes that are easy to follow.  Sounds so simple doesn't it?</p>
<h3>Closing Keynote: Bad Ruby - Stuart Halloway</h3>
<p>Stuart Holloway closed RubyNation with a talk on Bad Ruby.  Playing off of a point made earlier in Rich Kilmer's talk about Ruby becoming mainstream, Stuart noted that now was the time for Ruby developers to begin to establish best practices for the language so that common pitfalls can be avoided when mainstream developers start to migrate to Ruby.  (Assuming of course "mainstream" developers actually migrate to Ruby).</p>
<h3>Conference Wrap Up</h3>
<p>Overall the conference was pretty great.  Day two was a little less energetic than day one, but that may not be too surprising seeing as how it was on a Saturday.  I was a little disappointed that Bruce Tate wasn't able to make the conference because I was really looking forward to hearing him speak, but I was pleasantly surprised at the quality of the other speakers.  I know that a lot of people put a lot of hard work into the conference so I'd personally like to thank everyone responsible for putting on this years conference and I can't wait to attend again next year.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.justinspradlin.com/general/ruby-nation-day-2-wrap-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby Nation: Day 1 Wrap Up</title>
		<link>http://www.justinspradlin.com/general/ruby-nation-day-1-wrap-up/</link>
		<comments>http://www.justinspradlin.com/general/ruby-nation-day-1-wrap-up/#comments</comments>
		<pubDate>Fri, 01 Aug 2008 15:59:26 +0000</pubDate>
		<dc:creator>Justin Spradlin</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.justinspradlin.com/?p=17</guid>
		<description><![CDATA[Ruby experts and enthusiasts from around the country met in Washington, D.C. today for the first annual RubyNation conference.  I always think it's awesome to get together with industry leaders to absorb and share new information and insights.  I've been to quite a few tech conferences in the past, but I've never been [...]]]></description>
			<content:encoded><![CDATA[<p>Ruby experts and enthusiasts from around the country met in Washington, D.C. today for the first annual <a href="http://www.rubynation.org">RubyNation</a> conference.  I always think it's awesome to get together with industry leaders to absorb and share new information and insights.  I've been to quite a few tech conferences in the past, but I've never been as engaged and attentive as I was today.  There is an energy around Ruby and Rails that I have yet to witness with other technologies.  I continue to be amazed by how passionate and open the community is as well.  I met and talked with more people today than all of the other conferences I've attended combined.</p>
<p>In case you weren't able to make it, here's a quick rundown of today's events:</p>
<span id="more-17"></span>
<h3>Opening Keynote: Ceremony vs. Essence - Neal Ford</h3>
<p><a href="http://memeagora.blogspot.com/">Neal Ford</a> is a seasoned consultant and speaker that I've seen present on more than one occasion.  I've always enjoyed his presentations, but his talk today really hit home with me.  Neal's talk basically boiled down to the fact that we developers need to <a href="http://en.wikipedia.org/wiki/KISS_principle">Keep It Simple (KISS)</a> and avoid the "accidental complexity" that is often unnecessarily added to the problems we are trying to solve.  I've listen rhetoric like this a 1,000 times, but I've never heard it articulated so elegantly.  It was literally like he was looking inside of my head and expressing the way I (and likely a lot of developers) feel about the current state of the industry (especially if you are a Java programmer like me).</p>
<h3>DSLs and Ruby: Blurring the Lines Between Programs And Data - Russ Olsen</h3>
<p>I used to work with Russ at a <a href="http://www.fgm.com">FGM</a> so I was really looking forward to hearing him speak.  Russ has become quite a leader in the Ruby community especially after publishing his first book: <a href="http://www.amazon.com/Design-Patterns-Ruby-Russ-Olsen/dp/0321490452">Design Patterns in Ruby</a>.  Russ's talk centered around Domain Specific Languages (DSLs) and how relatively easy it is to implement one using the Ruby language.  During his presentation Russ put together a simple Internal DSL for example purposes and also discussed use cases for when it is appropriate to create a DSL to solve a problem.</p>
<h3>The Culture of Innovation in Ruby - Glenn Vanderburg</h3>
<p>Innovation in testing frameworks in Ruby was the topic of Glenn Vanderburg's talk.  Glenn discussed some of the interesting testings frameworks available in the Ruby community (<a href="http://rspec.info/">Rspec</a>, <a href="http://mocha.rubyforge.org/">Mocha</a>, <a href="http://onestepback.org/software/flexmock/">Flex Mock</a>, <a href="http://thoughtbot.com/projects/shoulda">Shoulda</a>) and compared them to some of the stagnant frameworks in the Java community (<a href="http://www.junit.org/">JUnit</a>, <a href="http://testng.org/doc/">TestNG</a>).  Glenn also pointed out how Ruby's testing frameworks tend to make it much easier to mock objects and create more thorough tests with much less effort than the equivalent tests in the Java world.</p>
<h3>Living on the Edge - Yehuda Katz</h3>
<p>Yehuda Katz of <a href="http://engineyard.com/">EngineYard</a> talked about some of the new(er) technologies that are emerging in the Ruby community including <a href="http://merbivore.com/">Merb</a>, <a href="http://datamapper.org/">DataMapper</a>, Sake, Thor, YARDoc, and <a href="http://github.com/">GitHub</a>.  DataMapper looks like an especially interesting alternative to the incumbent ORM ActiveRecord.  It promises thread safety and increased performance which are obviously two great things.  GitHub looks pretty cool too.  I'm not quite ready to abandon <a href="http://subversion.tigris.org/">Subversion</a> just yet, but I will definitely be checking out <a href="http://git.or.cz/">Git</a> in the near future.</p>
<h3>Lightning Talks</h3>
<p>Chris Bucchere, David Jones, Simon Kaczor, and Bryan Liles all gave lightening talks today on a variety of topics including social networking, state machines, command line libraries, and testing respectively.  All of the talks presented useful information, but Bryan Liles was without a doubt the most entertaining speaker of the day.  He made it through about 65 slides in 15 minutes and was still able to convey a very important message about how often developers should be testing their code.  Check out his blog at: <a href="http://smartic.us/">http://smartic.us/</a></p>
<h3>Archaeopteryx: A Ruby MIDI Generator - Giles Bowkett</h3>
<p>I actually wasn't able to attend Giles Bowkett's session because I had a previous engagement to attend, but I did get a chance to view some <a href="http://gilesbowkett.blogspot.com/2008/02/archaeopteryx-ruby-midi-generator.html">screencasts</a> that show off his Ruby MIDI Generator.  Pretty cool stuff.</p>
<h3>Tomorrow</h3>
<p>Tomorrow looks to be a pretty exciting day as well.  I'm especially looking forward to talks from my former co-worker Dave Bock and author Stuart Holloway.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.justinspradlin.com/general/ruby-nation-day-1-wrap-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Putting Google Finance to REST with Ruby</title>
		<link>http://www.justinspradlin.com/programming/putting-google-finance-to-rest-with-ruby/</link>
		<comments>http://www.justinspradlin.com/programming/putting-google-finance-to-rest-with-ruby/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 06:43:10 +0000</pubDate>
		<dc:creator>Justin Spradlin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://www.justinspradlin.com/?p=16</guid>
		<description><![CDATA[RubyNation is just a week and a half away and in order to prepare myself I thought I'd brush up on some Ruby and Rails in the days preceding the conference.  I don't use Ruby on a regular basis, but I'm a huge fan of dynamic languages so I'm really looking forward to attending [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.rubynation.org/">RubyNation</a> is just a week and a half away and in order to prepare myself I thought I'd brush up on some <a href="http://www.ruby-lang.org/">Ruby</a> and <a href="http://www.rubyonrails.org/">Rails</a> in the days preceding the conference.  I don't use Ruby on a regular basis, but I'm a huge fan of dynamic languages so I'm really looking forward to attending the conference and finding out what's new in the Ruby community.</p>
<p>By day I'm a Java developer, but I've also spent a fair amount of time studying Groovy.  Learning Groovy has been my "training wheels" approach to understanding dynamic languages.  Studying Groovy has helped me grasp new (new to me at least) concepts like <a href="http://www.justinspradlin.com/?s=metaprogramming">Metaprogramming</a> and Domain Specific Languages all from the comfort of my Java environment.</p>
<span id="more-16"></span>
<p>As a simple exercise I thought it would be interesting to rewrite the code from my <a href="http://www.justinspradlin.com/programming/putting-google-finance-to-rest-with-groovy/">last blog entry</a> in Ruby to see how it compares to the Groovy code I originally wrote.  So without further ado let's check out the code:</p>
<h3>Authenticating with Google</h3>
<p>In order to use the Google Finance API we need to first authenticate with Google by sending our <a href="https://www.google.com/accounts/NewAccount">Google Account</a> username and password to Google's client login URL: <strong>https://www.google.com/accounts/ClientLogin</strong>.</p>
<div class="codeBlock">
	<pre><code>def create_auth_token(username, password)
  https = Net::HTTP.new('www.google.com', <strong>443</strong>)
  <strong>https.use_ssl = true</strong>
  path = '/accounts/ClientLogin'

  query_string = "Email=#{username}&amp;Passwd=#{password}
                 &amp;service=finance&amp;source=company-groovyfinance-1.0"

  https.verify_mode = OpenSSL::SSL::VERIFY_NONE # don't display warnings

  response = https.<strong>post(</strong>path, query_string<strong>)</strong>

  if response.code == '200'
    return response.body[/Auth=(.*)/, 1] # The authorization token
  end

  return "Error"
end</code></pre>
</div>
<p>In the code above we create an <code>http</code> object and give it the correct URI and path to Google's login service.  We then send in a query string with our username, password, service, and source (application name).  If everything succeeds Google returns an Authentication token which we will set in the headers in subsequent calls to Google's service.</p>
<p>This code isn't much different from the Groovy code in my previous entry, but I do like the way Ruby allows <code>POST</code> calls directly on the <code><strong>http</strong></code> object.  This obsoletes the <code>processRequest()</code> method found in my Groovy code.</p>
<h3>Creating a Portfolio</h3>
<p>We can create a new portfolio in our Google Finance account by executing calls to the following method:</p>
<div class="codeBlock">
	<pre><code>def create_portfolio(authorization_token, portfolio_name)
  headers={}
  headers["Authorization"] = "GoogleLogin auth=#{authorization_token}"
  headers["Content-Type"] = "application/atom+xml"

  http = Net::HTTP.new('finance.google.com')
  path = "/finance/feeds/default/portfolios"

  atom_string = "&lt;?xml version='1.0'?&gt;
  &lt;entry xmlns='http://www.w3.org/2005/Atom'
         xmlns:gf='http://schemas.google.com/finance/2007'
         xmlns:gd='http://schemas.google.com/g/2005'&gt;
         &lt;title type='text'&gt;<strong>#{portfolio_name}</strong>&lt;/title&gt;
         &lt;gf:portfolioData currencyCode='USD'/&gt;
  &lt;/entry&gt;"

  response = <strong>http.post(</strong>path, atom_string, headers<strong>)</strong>

  if response.code == '201'
    doc = REXML::Document.new(response.body)
    return doc.root.elements["id"].text[/portfolios\/(.*)/, 1] #portfolio id
  end

  return "Error"
end</code></pre>
</div>
<p>This code is almost identical to the Groovy code I wrote <a href="http://www.justinspradlin.com/programming/putting-google-finance-to-rest-with-groovy/">last time</a> but I do really like the way Ruby allows you to place header attributes into a <code>Hash</code> and send them directly with a call to <code><strong>http.post()</strong></code>.</p>
<h3>Placing an Order</h3>
<p>Just like the example above, placing an order (stock trade) means that we need to create an <code><a href="http://en.wikipedia.org/wiki/Atom_(standard)">Atom</a></code> feed with our transaction attributes (transaction type, number of shares, etc.) and send them to a Google resource end point.  This end point in our case is the URL of the specific portfolio in which we wish to place our new asset.</p>
<div class="codeBlock">
	<pre><code>def create_stock_transaction(authorization_token, ticker_symbol,
                             number_of_shares, transaction_type, portfolio_id)

  headers={}
  headers["Authorization"] = "GoogleLogin auth=#{authorization_token}"
  headers["Content-Type"] = "application/atom+xml"

  http = Net::HTTP.new('finance.google.com')
  path = "/finance/feeds/default/portfolios/<strong>#{portfolio_id}</strong>/positions/" +
         "<strong>#{CGI::escape(ticker_symbol)}</strong>/transactions"

  transaction_time = Time.now.strftime("%Y-%m-%dT%H:%M:%S.000")

  atom_string = "&lt;?xml version='1.0'?&gt;
  &lt;entry xmlns='http://www.w3.org/2005/Atom'
         xmlns:gf='http://schemas.google.com/finance/2007'
         xmlns:gd='http://schemas.google.com/g/2005'&gt;
         &lt;gf:transactionData date='<strong>#{transaction_time}</strong>'
             shares='<strong>#{number_of_shares}</strong>' type='<strong>#{transaction_type}</strong>' /&gt;
  &lt;/entry&gt;"

  response = <strong>http.post(</strong>path, atom_string, headers<strong>)</strong>

  if response.code == '201'
    return response.body
  end

  return "Error"
end</code></pre>
</div>
<p>Once again the Ruby code looks nearly identical to the Groovy code.  We set the correct headers, generate a well formed Atom feed, and the post our data to Google.  If all goes well, the transaction will be made and an <code>Atom</code> representation of the transaction will be returned to the client.</p>
<h3>Groovy vs. Ruby Thoughts</h3>
<p>There are probably "Rubyer" ways to write the code samples listed above, but I did find it interesting that the code I wrote in Ruby was so similar to the code that I wrote in Groovy.  I'm not sure whether or not the similarities are due to the subjective nature of having the same programmer write both samples or if it's due to the fact that the languages are so similar to begin with.</p>
<p>Either way, exploring a new language (albeit a similar language) did give me some additional perspective.  I found myself bouncing back and forth between the Groovy and Ruby code comparing how similar tasks were performed in each language.  This type of information is always useful when trying to determine which technology is the right tool to use for a specific job.</p>
<p>In addition, studying Ruby <a href="http://www.justinspradlin.com/programming/putting-google-finance-to-rest-with-groovy/#comments">helped me write better Groovy code</a>.  In the create_auth_token() method in the Ruby sample a <a href="http://en.wikipedia.org/wiki/Regular_expression">regular expression</a> is used to parse the authentication token from the returned string.  I was able to take this regular expression code and apply it to the same method (createAuthToken()) in my Groovy code to improve its readability.</p>
<h3>References</h3>
<br/><a href="http://www.justinspradlin.com/downloads/rubyfinance.zip">Download the Code</a><br/><br/>
<a href="http://code.google.com/apis/gdata/index.html">Google Data API Developers Guide</a><br/>
<a href="http://code.google.com/apis/finance/developers_guide_protocol.html">Google Finance Developers Guide</a><br/>
<a href="http://code.google.com/apis/finance/reference.html">Google Finance Reference</a><br/><br/>
<a href="http://code.google.com/support/bin/answer.py?answer=93164&amp;topic=12027">Using Ruby with the Google Data APIs</a><br/>
<a href="http://www.germane-software.com/software/rexml/docs/tutorial.html">REXML Guide</a><br/>
<h3>Disclaimer</h3>
<p>Again... I am in no way endorsing any of the companies mentioned in this blog entry and all company references are for example purposes only.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.justinspradlin.com/programming/putting-google-finance-to-rest-with-ruby/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>
