<?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>brant interactive</title>
	<atom:link href="http://brantinteractive.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://brantinteractive.com</link>
	<description></description>
	<lastBuildDate>Fri, 27 Jan 2012 13:46:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>RakeUI &#8211; a Rails 3.1 Engine that provides a web UI for Rake tasks built with Node.js and Socket.io</title>
		<link>http://brantinteractive.com/2011/12/21/rakeui-a-rails-3-1-engine-that-provides-a-web-ui-for-rake-tasks-built-with-node-js-and-socket-io/</link>
		<comments>http://brantinteractive.com/2011/12/21/rakeui-a-rails-3-1-engine-that-provides-a-web-ui-for-rake-tasks-built-with-node-js-and-socket-io/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 19:52:41 +0000</pubDate>
		<dc:creator>rbrant</dc:creator>
				<category><![CDATA[Node]]></category>
		<category><![CDATA[Ruby/Rails]]></category>

		<guid isPermaLink="false">http://ec2-50-19-95-138.compute-1.amazonaws.com/wordpress/?p=575</guid>
		<description><![CDATA[I&#8217;ve been determined to find a reason to use Node.js in a project since, as the adage goes, you have to sart somewhere. What I came up with was something that I&#8217;m actually going to use in future projects, I think. I&#8217;ve often wished there were an easy way to give clients access to rake [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>I&#8217;ve been determined to find a reason to use Node.js in a project since, as the adage goes, you have to sart somewhere. What I came up with was something that I&#8217;m actually going to use in future projects, I think.</p>
<p>I&#8217;ve often wished there were an easy way to give clients access to rake tasks, but in the browser. Rake tasks are great because you can provide real time feedback in the terminal to show the user what&#8217;s going on as it&#8217;s happening. Node.js along with Socket.io make creating this experience in the browser really easy.</p>
<p>This project is a Rails 3.1 engine, so it&#8217;s super easy to hook up in your Rails application. Aside from using Rails 3.1+, you need to have Node.js and Socket.io installed. So to get this running:</p>
<p>In your Gemfile:</p>
<pre>gem 'rake_ui', :git =&gt; "git://github.com/rbrant/rake_ui.git"</pre>
<p>In your routes.rb file:</p>
<pre>Rails.application.routes.draw do  
  mount RakeUi::Engine =&gt; "/rake_ui"
end</pre>
<p>Then you need to start the Node server. From your app&#8217;s root:</p>
<pre>rake app:start_node_server</pre>
<p>Once your Rails app is started, visit /rake_ui to see your rake tasks. All stdout generated in your task via something like:</p>
<pre>$stdout.puts "hey now"</pre>
<p>will be displayed in the black window to the right of the Rake task command listing.</p>
<p><a href="http://brantinteractive.com/wp-content/uploads/2011/12/rake_ui.png"><img src="http://brantinteractive.com/wp-content/uploads/2011/12/rake_ui-300x190.png" alt="" title="RakeUI" width="300" height="190" class="aligncenter size-medium wp-image-603" /></a></p>
<p>They way it works is that when the app is initialized, all the available rake tasks are stored in memory along with an ID key. The index page displays all he rake tasks and identifies them by their ID. When a task is selected, it get identified and then called via:</p>
<pre>Kernel.system("#{@rake_task.command} #{@rake_task.arguments} &amp;&gt; #{Rails.root}/log/rake.log")</pre>
<p>As you can see, stdout is sent to a log file. This log file gets tailed by Node and hooked up to the browser via Socket.io. Very cool, eh? I need to find a real node project..</p>
<p>To make this engine truly useful, I&#8217;ll probably add a way to blacklist certain tasks so they aren&#8217;t available in the UI. Probably not a good idea to allow your clients to drop their database. I also need to scrub the optional arguments.</p>
<p>The project is available on Github:</p>
<p><a href="https://github.com/rbrant/rake_ui">https://github.com/rbrant/rake_ui</a></p>
]]></content:encoded>
			<wfw:commentRss>http://brantinteractive.com/2011/12/21/rakeui-a-rails-3-1-engine-that-provides-a-web-ui-for-rake-tasks-built-with-node-js-and-socket-io/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using EC2 to split up and expedite large processing jobs</title>
		<link>http://brantinteractive.com/2011/01/04/using-ec2-to-split-up-and-expedite-large-processing-jobs/</link>
		<comments>http://brantinteractive.com/2011/01/04/using-ec2-to-split-up-and-expedite-large-processing-jobs/#comments</comments>
		<pubDate>Wed, 05 Jan 2011 02:37:59 +0000</pubDate>
		<dc:creator>rbrant</dc:creator>
				<category><![CDATA[Ruby/Rails]]></category>

		<guid isPermaLink="false">http://brantinteractive.com/?p=532</guid>
		<description><![CDATA[The problem: You have a large number of records that need to be modified. You don&#8217;t have the processing resources to accomplish this as quickly as you&#8217;d like. The solution: Break the data into chunked csv files, with each file containing a certain number of records. Spin up a bunch of EC2 instances whereby each [...]]]></description>
			<content:encoded><![CDATA[<p></p><p><strong>The problem:</strong><br />
You have a large number of records that need to be modified. You don&#8217;t have the processing resources to accomplish this as quickly as you&#8217;d like.</p>
<p><strong>The solution:</strong><br />
Break the data into chunked csv files, with each file containing a certain number of records. Spin up a bunch of EC2 instances whereby each one, on startup, processes one file. This also allows you to run a large number of processes concurrently to get the job done quickly. 100 &#8216;micro&#8217; instances all running at the same time will cost $10 per hour ($.10/hour). That&#8217;s not bad!</p>
<p><strong>Creating the chunked files</strong></p>
<pre>
file_num = 1

Thing.all.in_groups_of(2500, false) do |thing_group|
  csv_data = FasterCSV.generate do |csv|
    thing_group.each_with_index do |thing|
      csv << [thing.attr1, thing.attr2]
    end
  end
end

File.open("chunked_things/file#{file_num}.csv", 'w') {|f| f.write(csv_data) }
file_num += 1
</pre>
<p><strong>Configure an EC2 instance to serve as the source instance</strong><br />
Configure an EC2 instance from which you will create an AMI to be used to spawn the other worker instances. The important part is to make sure this instance has a copy of all the chunked files created above. I'll explain why later. <a href="http://bitnami.org/stack/rubystack">I used an AMI from bitnami</a>,<a href="http://aws.amazon.com/amis/4269"> this one to be specific (listed toward the bottom of the page)</a>. It's an EBS backed AMI which makes creating AMIs from running instances easier than from S3 backed ones. This may have changed, not sure.</p>
<p><strong>Use cron to run the script at start up</strong><br />
Create a cron task set to run when the instance is booted. You can use the @reboot shortcut to accomplish this:</p>
<pre>@reboot /path/to/ruby /path/to/your/script</pre>
<p>The goal here is to have your script run when the server boots. This would be pretty straight forward, however, we need to be sure all the EC2 instances don't process the same file at once, or process the same file twice. Enter SQS. </p>
<p><strong>SQS</strong><br />
<a href="http://aws.amazon.com/sqs/">SQS basically allows you to create a simple queue that holds messages</a>. For us, these messages take the format of the names of all the files we want to process. When the server boots, and the script runs, it hits the SQS service and asks for the name of a file. SQS responds with a message off the queue (which is the name of a file). That message is locked so no other requests will respond with it. Once the message is retrieved, you can pop is off the queue. Each spawned instance is guaranteed to get it's own filename.</p>
<p><a href="http://rightscale.rubyforge.org/right_aws_gem_doc/">right_aws is an awesome wrapper for AWS</a>. The code to create the create the queue looks like this:</p>
<pre>
sqs   = RightAws::SqsGen2.new(aws_key, aws_secret)
queue = RightAws::SqsGen2::Queue.create(sqs, 'chunk_queue')
</pre>
<p>Populate the queue with your filenames</p>
<pre>
queue.push 'your_filename'
</pre>
<p><strong>Processing the file</strong><br />
To get a filename from the queue:</p>
<pre>
chunked_filename = queue.pop.to_s
</pre>
<p>Now we have the file with CSV data to process. Loop through it, hitting service you need to. </p>
<p><strong>Push your modifed data back to S3</strong><br />
When you are finished processing your file, you'll want to put the results somewhere. S3 is an obvious choice. Again with right_aws, it's pretty easy. This will basically write your data back to a file on S3:</p>
<pre>
s3     = RightAws::S3.new(aws_key, aws_secret)
bucket = s3.bucket(s3_bucket_name)
key    = RightAws::S3::Key.create(bucket, "#{s3_bucket_key}#{chunked_filename}")
key.put(your_data)
</pre>
<p><strong>Altogether now</strong>, this is some pseudo code(not tested) that addresses the core parts of the process. This is the script that would be executed at start up:</p>
<pre>
require 'rubygems'
require 'right_aws'
require 'fastercsv'

# aws
aws_key    = 'your key'
aws_secret = 'your secret'

# s3 bucket
s3_bucket_name = 'your_bucket'
s3_bucket_key  = 'name_of_key'

sqs   = RightAws::SqsGen2.new(aws_key, aws_secret)
queue = RightAws::SqsGen2::Queue.create(sqs, 'chunk_queue')

# pop a file anme off the queue
chunked_filename = queue.pop.to_s

modified_data = []

# process the filename SQS gave us (a copy of all files is on each instance)
file_to_process = "#{File.expand_path(File.dirname(__FILE__))}/#{chunked_filename}"

FasterCSV.foreach(file_to_process) do |row|
  data_for_api = "#{row[0]}, #{row[1]}, #{row[2]} #{row[3]}"
  results  = # hit your web service or do what you need to here

  # use api results
  modified_data << [results.value1, results.value2]
end

# generating csv data
csv_data = FasterCSV.generate{ |csv| modified_data.each{ |modified| csv << modified } }

# put the file on S3
s3       = RightAws::S3.new(aws_key, aws_secret)

# grab the bucket
bucket   = s3.bucket(s3_bucket_name)

# create the S3 key where the csv data will be stored
key      = RightAws::S3::Key.create(bucket, "#{s3_bucket_key}#{chunked_filename}")

# write the data to S3
key.put(csv_data)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://brantinteractive.com/2011/01/04/using-ec2-to-split-up-and-expedite-large-processing-jobs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Crash course in Firefox extension development &#8211; adding the new &#8216;micro&#8217; instance type to the elasticfox extension</title>
		<link>http://brantinteractive.com/2010/09/14/crash-course-in-firefox-extension-development-adding-the-new-micro-instance-type-to-the-elasticfox-extension/</link>
		<comments>http://brantinteractive.com/2010/09/14/crash-course-in-firefox-extension-development-adding-the-new-micro-instance-type-to-the-elasticfox-extension/#comments</comments>
		<pubDate>Tue, 14 Sep 2010 19:25:11 +0000</pubDate>
		<dc:creator>rbrant</dc:creator>
				<category><![CDATA[Ruby/Rails]]></category>

		<guid isPermaLink="false">http://brantinteractive.com/2010/09/14/crash-course-in-firefox-extension-development-adding-the-new-micro-instance-type-to-the-elasticfox-extension/</guid>
		<description><![CDATA[Click here to download: ec2u-rbrant.xpi (419 KB) So I&#8217;m all set to take advantage of Amazon Web Service&#8217;s new &#8216;micro&#8217; instance type on EC2 (yup, another client moving to EC2). I need to manage it via the elasticfox Firefox extension, but the micro instance type isn&#8217;t an option yet in the new instance dialog. Since [...]]]></description>
			<content:encoded><![CDATA[<p></p><div class='posterous_autopost'>
<div style='padding: 5px 5px 10px 5px;margin-top: 5px;border: 1px solid #ddd;background-color: #fff;line-height: 16px'>
<div style="float: left;margin-right: 5px;overflow: visible"><a href='http://posterous.com/getfile/files.posterous.com/rbrant/PAD09hoKBmq1TjdBpcaklvyFDuhI8WdjGEjW2SOpq26HWm6hrui0sgEMXaiC/ec2u-rbrant.xpi'><img src='http://posterous.com/images/filetypes/unknown.png' style='border: none' /></a></div>
<div style="font-size: 10px;color: #424037;line-height: 16px">Click here to download:</div>
<p>       <b><a href='http://posterous.com/getfile/files.posterous.com/rbrant/PAD09hoKBmq1TjdBpcaklvyFDuhI8WdjGEjW2SOpq26HWm6hrui0sgEMXaiC/ec2u-rbrant.xpi'>ec2u-rbrant.xpi</a></b> <span style="font-size: 10px;color: #424037">(419 KB)</span>       </div>
<p>So I&#8217;m all set to take advantage of Amazon Web Service&#8217;s new &#8216;micro&#8217; <br />instance type on EC2 (yup, another client moving to EC2). I need to <br />manage it via the elasticfox Firefox extension, but the micro instance <br />type isn&#8217;t an option yet in the new instance dialog.
<p /> Since it&#8217;s open source, I figured I&#8217;d see how difficult it would be to <br />change it myself. Turns out to be not difficult at all. Got the code <br />here:
<p /> <a href="http://sourceforge.net/projects/elasticfox/develop">http://sourceforge.net/projects/elasticfox/develop</a>
<p /> And then tracked down the relevant code which handles the setting of <br />the instance type:
<p /> /trunk/src/chrome/content/ec2ui/newinstancedialog.js
<p /> and added(around line 255):
<p /> typeMenu.appendItem(&#8220;t1.micro&#8221;, &#8220;t1.micro&#8221;);
<p /> But I still needed to build the extension. It&#8217;s probably easy to do, <br />but after reading <br /><a href="https://developer.mozilla.org/en/Building_an_Extension">https://developer.mozilla.org/en/Building_an_Extension</a>, I was directed <br />to another extension that has a number of utilities, including the <br />building of an extension:
<p /> <a href="https://addons.mozilla.org/en-US/firefox/addon/7434/">https://addons.mozilla.org/en-US/firefox/addon/7434/</a>
<p /> It makes it super easy. You just browse to the source and click build. <br />You&#8217;ll need to go: Tools &gt; Add Ons and then drag the xpi file there <br />for now.</p>
<p style="font-size: 10px">  <a href="http://posterous.com">Posted via email</a>   from <a href="http://rbrant.posterous.com/crash-course-in-firefox-extension-development">rich&#8217;s posterous</a>  </p>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://brantinteractive.com/2010/09/14/crash-course-in-firefox-extension-development-adding-the-new-micro-instance-type-to-the-elasticfox-extension/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ActsAsCachola &#8211; simple caching for AR models (everyone could use a little cachola)</title>
		<link>http://brantinteractive.com/2010/07/16/actsascachola-simple-caching-for-ar-models-everyone-could-use-a-little-cachola/</link>
		<comments>http://brantinteractive.com/2010/07/16/actsascachola-simple-caching-for-ar-models-everyone-could-use-a-little-cachola/#comments</comments>
		<pubDate>Fri, 16 Jul 2010 15:20:49 +0000</pubDate>
		<dc:creator>rbrant</dc:creator>
				<category><![CDATA[Ruby/Rails]]></category>

		<guid isPermaLink="false">http://brantinteractive.com/?p=460</guid>
		<description><![CDATA[And you thought all the clever caching names were taken. What is it ActsAsCachola is a plugin that lets you cache any class method by simply prepending ‘cachola_’ to the method name when calling it. Here’s how it works: Given the following model: class Internet < ActiveRecord::Base acts_as_cachola def self.get_a_million_numbers 1.upto(1_000_000).inject([]){ &#124;numbers, x&#124; numbers]]></description>
			<content:encoded><![CDATA[<p></p><p>And you thought all the clever caching names were taken.</p>
<h2>What is it</h2>
<p>ActsAsCachola is a plugin that lets you cache any class method by simply prepending ‘cachola_’ to the method name when calling it. Here’s how it works:</p>
<p>Given the following model:</p>
<pre>
class Internet < ActiveRecord::Base
  acts_as_cachola

  def self.get_a_million_numbers
    1.upto(1_000_000).inject([]){ |numbers, x| numbers << x }
  end
end
</pre>
<p>Now you can call the method, ‘cachola_get_a_million_numbers,’ and the return value of ‘get_a_million_numbers’ will be cached automatically.</p>
<p>Note that if the method accepts arguments, each unique call will have its own key in the cache. For example:</p>
<pre>
class Internet < ActiveRecord::Base
  acts_as_cachola

  def self.get_numbers(to_number)
    1.upto(to_number).inject([]){ |numbers, x| numbers << x }
  end
end
</pre>
<p>Calling Internet.cachola_get_numbers(100) and Internet.cachola_get_numbers(500) will result in two keys (with different values) stored in the cache.</p>
<p>The cached method is then expired automatically when the class in which the plugin has been included is saved or destroyed. It’s restored to the cache the next time it’s called.</p>
<p>Now, what if your Internet class method ‘get_a_million_numbers’ depends on other objects getting saved or destroyed? That’s the other thing I wanted to make easier. Rather than setting up observers or sweepers, you can add the following to the other model:</p>
<pre>
class WhereAmI < ActiveRecord::Base
  acts_as_cachola_notifier => [:internet]
end
</pre>
<p>Now when your WhereAmI model is ether saved or destroyed, the cached methods in the Internet model will be deleted.</p>
<h2>Installation</h2>
<p>script/plugin install git://github.com/rbrant/acts_as_cachola.git</p>
<h2>Where is this going from here?</h2>
<p>Not sure. It does what I need it to do right now. It’s something I’ve found myself doing on two different projects that I thought would just make my life easier.</p>
<h2>Project Info</h2>
<p>ActsAsCachola is hosted on Github: <a href="http://github.com/rbrant/acts_as_cachola">http://github.com/rbrant/acts_as_cachola</a>, where your contributions, forkings, comments and feedback are greatly appreciated. Please do add tests if you want me to pull in any changes.</p>
]]></content:encoded>
			<wfw:commentRss>http://brantinteractive.com/2010/07/16/actsascachola-simple-caching-for-ar-models-everyone-could-use-a-little-cachola/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I want to show you some SAX.</title>
		<link>http://brantinteractive.com/2010/03/12/i-want-to-show-you-some-sax/</link>
		<comments>http://brantinteractive.com/2010/03/12/i-want-to-show-you-some-sax/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 18:11:05 +0000</pubDate>
		<dc:creator>rbrant</dc:creator>
				<category><![CDATA[Ruby/Rails]]></category>

		<guid isPermaLink="false">http://brantinteractive.com/?p=440</guid>
		<description><![CDATA[I had to process some pretty big xml docs recently from the USPTO. Each doc is about 60mb and (oddly enough) contains several thousand individual documents all concatenated. So the document isn&#8217;t valid xml..but that&#8217;s a different story. The reason for writing this was to show a quick demo of how to use SAX to [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>I had to process some pretty big xml docs recently from the USPTO. Each doc is about 60mb and (oddly enough) contains several thousand individual documents all concatenated. So the document isn&#8217;t valid xml..but that&#8217;s a different story. </p>
<p>The reason for writing this was to show a quick demo of how to use SAX to process a large XML file. <a href="http://www.xml.com/pub/a/2001/02/14/perlsax.html">You can read about SAX here</a>, but basically, SAX (Simple API for XML) is an event-driven model that solves the problem of having to read an entire tree structure into memory which can be realllly sloooow, and instead reads the stream of data and raises events along the way.</p>
<p>The code below uses the <a href="http://nokogiri.org/">Nokogiri</a> library (which as a side note has this odd, albeit entertaining tagline: &#8220;XML is like violence &#8211; if it doesn’t solve your problems, you are not using enough of it.&#8221;). Most other XML parsing libraries also have SAX implementations.</p>
<p>What the code does below is looks for the root node of each doc and builds a string for each individual document. After the doc has been assembled, the doc can be processed via the more pleasant:</p>
<pre>
doc = Nokogiri::HTML(xml)
serial = doc.css("application-reference document-id doc-number").inner_text
</pre>
<p>So this ends up being sort of a hybrid and much, much faster than loading the entire doc at once. It would be faster not parsing the doc again at all but the docs have too much nested complexity that requires the ability to use xpath to get at what I need.</p>
<p><script src="http://gist.github.com/330542.js?file=sax"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://brantinteractive.com/2010/03/12/i-want-to-show-you-some-sax/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Good stuff from Bob Martin on software. Like the stuff at 11:20 inre 	tech/biz disconnect. Not sure about the shirt, however.</title>
		<link>http://brantinteractive.com/2010/02/17/good-stuff-from-bob-martin-on-software-like-the-stuff-at-1120-inre-techbiz-disconnect-not-sure-about-the-shirt-however/</link>
		<comments>http://brantinteractive.com/2010/02/17/good-stuff-from-bob-martin-on-software-like-the-stuff-at-1120-inre-techbiz-disconnect-not-sure-about-the-shirt-however/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 21:36:32 +0000</pubDate>
		<dc:creator>rbrant</dc:creator>
				<category><![CDATA[Ruby/Rails]]></category>

		<guid isPermaLink="false">http://brantinteractive.com/2010/02/17/good-stuff-from-bob-martin-on-software-like-the-stuff-at-1120-inre-techbiz-disconnect-not-sure-about-the-shirt-however/</guid>
		<description><![CDATA[Posted via email from Rich&#8217;s posterous]]></description>
			<content:encoded><![CDATA[<p></p><div class='posterous_autopost'>
<p style="font-size: 10px">  <a href="http://posterous.com">Posted via email</a>   from <a href="http://rbrant.posterous.com/good-stuff-from-bob-martin-on-software-like-t">Rich&#8217;s posterous</a>  </p>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://brantinteractive.com/2010/02/17/good-stuff-from-bob-martin-on-software-like-the-stuff-at-1120-inre-techbiz-disconnect-not-sure-about-the-shirt-however/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Seth Godin&#8217;s ebook, &#8216;What matters now&#8217; Free download. Tons of great 	ideas/things to think about.</title>
		<link>http://brantinteractive.com/2009/12/15/seth-godins-ebook-what-matters-now-free-download-tons-of-great-ideasthings-to-think-about/</link>
		<comments>http://brantinteractive.com/2009/12/15/seth-godins-ebook-what-matters-now-free-download-tons-of-great-ideasthings-to-think-about/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 14:18:10 +0000</pubDate>
		<dc:creator>rbrant</dc:creator>
				<category><![CDATA[Ruby/Rails]]></category>

		<guid isPermaLink="false">http://brantinteractive.com/2009/12/15/seth-godins-ebook-what-matters-now-free-download-tons-of-great-ideasthings-to-think-about/</guid>
		<description><![CDATA[Download now or preview on posterous what-matters-now-2.pdf (3073 KB) Posted via email from Rich&#8217;s posterous]]></description>
			<content:encoded><![CDATA[<p></p><div style='padding: 5px 5px 10px 5px;margin-top: 5px;border: 1px solid #ddd;background-color: #fff;line-height: 16px'>
<div style="float: left;margin-right: 5px;overflow: visible"><a href='http://posterous.com/getfile/files.posterous.com/rbrant/XSiM2ov12LAaCYnUy61I90kCiAhpVUFCvJLeB70QfGM8dpETrotwE94TmDHz/what-matters-now-2.pdf'><img src='http://posterous.com/images/filetypes/pdf.png'></a></div>
<div style="font-size: 10px;color: #424037;line-height: 16px">Download now or <a href='http://rbrant.posterous.com/seth-godins-ebook-what-matters-now-free-downl'>preview on posterous</a></div>
<p>       <b><a href='http://posterous.com/getfile/files.posterous.com/rbrant/XSiM2ov12LAaCYnUy61I90kCiAhpVUFCvJLeB70QfGM8dpETrotwE94TmDHz/what-matters-now-2.pdf'>what-matters-now-2.pdf</a></b> <span style="font-size: 10px;color: #424037">(3073 KB)</span>       </div>
<p style="font-size: 10px">  <a href="http://posterous.com">Posted via email</a>   from <a href="http://rbrant.posterous.com/seth-godins-ebook-what-matters-now-free-downl">Rich&#8217;s posterous</a>  </p>
]]></content:encoded>
			<wfw:commentRss>http://brantinteractive.com/2009/12/15/seth-godins-ebook-what-matters-now-free-download-tons-of-great-ideasthings-to-think-about/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Project review: ifwinsight.com</title>
		<link>http://brantinteractive.com/2009/12/06/project-review-ifwinsight-com/</link>
		<comments>http://brantinteractive.com/2009/12/06/project-review-ifwinsight-com/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 01:09:22 +0000</pubDate>
		<dc:creator>rbrant</dc:creator>
				<category><![CDATA[Ruby/Rails]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Tools & Tips]]></category>

		<guid isPermaLink="false">http://brantinteractive.com/?p=406</guid>
		<description><![CDATA[It&#8217;s easy to forget what you&#8217;ve learned and what tools you used from project to project. I thought it might be worthwhile to sort of sum up these things either on a weekly basis or project basis. I had a lot of fun on a recent project and thought it would be a good place [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>It&#8217;s easy to forget what you&#8217;ve learned and what tools you used from project to project. I thought it might be worthwhile to sort of sum up these things either on a weekly basis or project basis. I had a lot of fun on a recent project and thought it would be a good place to start. I recently built what is described as a &#8216;tool for intelligently searching US patent application Image File Wrappers (IFWs).&#8217;</p>
<p>Technically, the system allows users to upload PDF documents and have their content indexed and made searchable. The documents are reasonably sized, averaging 25 megs each with several hundred pages. So once uploaded to the server, they are handed to <a href="http://github.com/collectiveidea/delayed_job">delayed job</a> to be processed in the background. I&#8217;m using collective idea&#8217;s fork after watching <a href="http://railscasts.com/episodes/171-delayed-job">Ryan Bates&#8217; screencast on delayed job</a> that points out this fork has a few generators and rake tasks not part of the original.</p>
<p>In order to index the document, the PDF needs to be examined by OCR (optical character recognition) software. But before the OCR software can do its OCR-ing, it needs to have an image to examine. So we need to convert the individual PDF pages into images. To accomplish that, I used <a href="http://pages.cs.wisc.edu/~ghost/">ghostscript</a>. It&#8217;s really easy to use and fast. You can hand ghostscript the document, and it will churn out a an image of each PDF page, in the resolution of your choice. I&#8217;m using 300&#215;300, which seems to be a nice balance between processing time, space, and readability/ocr results.</p>
<p>Once the document has been converted into images the OCR software, <a href="http://code.google.com/p/tesseract-ocr/">tesseract-ocr</a>, will iterate through each image and produce a text file with the contents of the page. Now, with a directory full of text files, it&#8217;s time to store the contents of each page in the database. That&#8217;s where <a href="http://sphinxsearch.com/">sphinx</a> and <a href="http://freelancing-god.github.com/ts/en/">thinking sphinx</a> come into play. Sphinx is the full text search engine and thinking sphinx is a &#8216;concise and easy-to-use Ruby library that connects ActiveRecord to the Sphinx search daemon, managing configuration and searching.&#8217; I actually started the project with ferret/acts_as_ferret, but after reading so many good reviews of sphinx, and my own problems with ferret, I switched. The only downside is that setup is a little trickier and thinking sphinx doesn&#8217;t automatically update the index the way acts_as_ferret does, so there&#8217;s a cron job that handles that. The indexer is super fast though, so frequent indexing isn&#8217;t a problem.</p>
<p>The site also offers multiple file download, and I used the rubyzip library which makes it simple to zip up a bunch of docs into one.</p>
<p>As for design, we used a theme from themeforest.net. I was impressed by the quality of generic templates they have. They aren&#8217;t free, but are dirt cheap &#8211; $5 or $10  for most. I&#8217;ve used</p>
<p>It&#8217;s a Rails application, so as for gems/plugins, the usual suspects are there:  acts_as_commentable, exception_notification, restful_authentication, role_requirement, mislav-will_paginate, attachment_fu, and a few others: slicehost, thinking-sphinx, delayed_job, and rubyzip.</p>
<p>The real jewel in the list is &#8216;<a href="http://github.com/josh/slicehost">slicehost</a>&#8216; which gives you a bunch of rake tasks for setting up your slice at <a href="http://www.slicehost.com/">slicehost</a>, which is my favorite hosting provider. </p>
<p>One other thing worth mentioning was an issue with the delayed_job process not stopping properly during deploys, so I kept getting multiple instances of delayed job running because the one running during the deploy never stopped. It was noted on github (with the solution below) in the issues section but I can&#8217;t find it now. Basically, the restart task looks like this:</p>
<pre>
desc "Restart the delayed_job process"
  task :restart, :roles => :app do
  stop
  wait_for_process_to_end('delayed_job')
  start
  end
end

def wait_for_process_to_end(process_name)
  run "COUNT=1; until [ $COUNT -eq 0 ]; do COUNT=`ps -ef | grep -v 'ps -ef' | grep -v 'grep' | grep -i '#{process_name}'|wc -l` ; echo 'waiting for #{process_name} to end' ; sleep 2 ; done"
end
</pre>
<p>As a final note, all the software used in this project is open source. I&#8217;m constantly reminded of that and impressed by it. My thanks to all who have contributed to the software used in this project!</p>
]]></content:encoded>
			<wfw:commentRss>http://brantinteractive.com/2009/12/06/project-review-ifwinsight-com/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>upgrading to snow leopard &#8211; issues with mysql and gems</title>
		<link>http://brantinteractive.com/2009/08/30/upgrading-to-snow-leopard-issues-with-mysql-and-gems/</link>
		<comments>http://brantinteractive.com/2009/08/30/upgrading-to-snow-leopard-issues-with-mysql-and-gems/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 01:02:42 +0000</pubDate>
		<dc:creator>rbrant</dc:creator>
				<category><![CDATA[Ruby/Rails]]></category>

		<guid isPermaLink="false">http://brantinteractive.com/2009/08/30/upgrading-to-snow-leopard-issues-with-mysql-and-gems/</guid>
		<description><![CDATA[Was definitely worth upgrading to snow leopard from leopard. My machine is noticeably quicker and I picked up quite a bit of new storage space, but it was not without its issues on the dev side of things. The most affected area so far has been mysql. You need to get the 64 bit version: [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Was definitely worth upgrading to snow leopard from leopard. My machine is noticeably quicker and I picked up quite a bit of new storage space, but it was not without its issues on the dev side of things. The most affected area so far has been mysql.</p>
<p>You need to get the 64 bit version:<br />
<a href="http://dev.mysql.com/downloads/mysql/5.1.html#macosx-dmg">http://dev.mysql.com/downloads/mysql/5.1.html#macosx-dmg</a></p>
<p>I know you can use my.cnf and point to your previous versions&#8217; data files, and then run mysql_upgrade, but that wasn&#8217;t working for me. I copied all the files from my previous install&#8217;s data directory and restarted the server. I suspect this method won&#8217;t work for all the different storage engines though.</p>
<p>You also need to reinstall any gems with native extensions.</p>
<p>The install itself, it&#8217;s worth noting, was a bit strange. It took a looong time, probably 120 minutes or so. The screen went dark toward the end. I was tempted to try restarting it because it seemed like it was hanging. It did eventually restart on its own, but when it restarted the screen was dark again. Magically after about three restarts it resolved itself.</p>
<p style="font-size: 10px;"><a href="http://posterous.com">Posted via email</a> from <a href="http://rbrant.posterous.com/upgrading-to-snow-leopard-issues-with-mysql-a">Rich&#8217;s posterous</a></p>
]]></content:encoded>
			<wfw:commentRss>http://brantinteractive.com/2009/08/30/upgrading-to-snow-leopard-issues-with-mysql-and-gems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Awesome talk at biz of software conf: Seth Godin on why marketing is 	too important to be left to the marketing department</title>
		<link>http://brantinteractive.com/2009/07/31/awesome-talk-at-biz-of-software-conf-seth-godin-on-why-marketing-is-too-important-to-be-left-to-the-marketing-department/</link>
		<comments>http://brantinteractive.com/2009/07/31/awesome-talk-at-biz-of-software-conf-seth-godin-on-why-marketing-is-too-important-to-be-left-to-the-marketing-department/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 18:24:44 +0000</pubDate>
		<dc:creator>rbrant</dc:creator>
				<category><![CDATA[Ruby/Rails]]></category>

		<guid isPermaLink="false">http://brantinteractive.com/2009/07/31/awesome-talk-at-biz-of-software-conf-seth-godin-on-why-marketing-is-too-important-to-be-left-to-the-marketing-department/</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p></p><p><object width="480" height="390" data="http://blip.tv/play/Ad6xPAI" type="application/x-shockwave-flash"><param name="src" value="http://blip.tv/play/Ad6xPAI" /><param name="allowfullscreen" value="true" /></object></p>
]]></content:encoded>
			<wfw:commentRss>http://brantinteractive.com/2009/07/31/awesome-talk-at-biz-of-software-conf-seth-godin-on-why-marketing-is-too-important-to-be-left-to-the-marketing-department/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

